struct uart_driver
每一款SoC的UART都需要去实现并定义个属于它自己uart_driver结构,uart_driver包含了串口设备名,串口驱动名,主次设备号,串口控制台(可选))等信息,还封装了tty_driver,定义在include/linux/serial_core.h:
struct uart_driver {
struct module *owner;
const char *driver_name;
const char *dev_name;
int major;
int minor;
int nr;
struct console *cons;
/*
* these are private; the low level driver should not
* touch these; they should be initialised to NULL
*/
struct uart_state *state;
struct tty_driver *tty_driver;
};
struct uart_state
每一个uart端口对应着一个uart_state,该结构体将uart_port与对应的circ_buf联系起来。uart_state有两个成员在底层串口驱动会用到:xmit和port。
struct uart_state {
struct tty_port port;
enum uart_pm_state pm_state;
struct circ_buf xmit;
atomic_t refcount;
wait_queue_head_t remove_wait;
struct uart_port *uart_port;
};
struct uart_port
uart_port存储的是与UART串口硬件相关的信息,需要芯片厂家定义自己的 uart_port 结构并填充它。
struct uart_ops
uart_ops定义了UART硬件相关相关的操作集,芯片厂家需要进行硬件寄存器级的适配其中各个操作
struct uart_ops {
unsigned int (*tx_empty)(struct uart_port *);
void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
unsigned int (*get_mctrl)(struct uart_port *);
void (*stop_tx)(struct uart_port *);
void (*start_tx)(struct uart_port *);
void (*throttle)(struct uart_port *);
void (*unthrottle)(struct uart_port *);
void (*send_xchar)(struct uart_port *, char ch);
void (*stop_rx)(struct uart_port *);
void (*enable_ms)(struct uart_port *);
void (*break_ctl)(struct uart_port *, int ctl);
int (*startup)(struct uart_port *);
void (*shutdown)(struct uart_port *);
void (*flush_buffer)(struct uart_port *);
void (*set_termios)(struct uart_port *, struct ktermios *new,
struct ktermios *old);
void (*set_ldisc)(struct uart_port *, struct ktermios *);
void (*pm)(struct uart_port *, unsigned int state,
unsigned int oldstate);
/*
* Return a string describing the type of the port
*/
const char *(*type)(struct uart_port *);
/*
* Release IO and memory resources used by the port.
* This includes iounmap if necessary.
*/
void (*release_port)(struct uart_port *);
/*
* Request IO and memory resources used by the port.
* This includes iomapping the port if necessary.
*/
int (*request_port)(struct uart_port *);
void (*config_port)(struct uart_port *, int);
int (*verify_port)(struct uart_port *, struct serial_struct *);
int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLL
int (*poll_init)(struct uart_port *);
void (*poll_put_char)(struct uart_port *, unsigned char);
int (*poll_get_char)(struct uart_port *);
#endif
};
uart驱动API
uart_register_driver用于注册UART设备,实际上就是tty_driver的注册,都是将uart的参数传递给tty_driver,后注册字符设备、分配设备文件、将驱动注册到tty_driver链表中。
uart驱动编写流程
经过对UART相关数据结构和API的分析,我们大概了解到,要实现一个串口驱动,我们需要定义以下数据结构:
- uart_driver结构,一个;
- uart_port结构,多个,取决于串口的数量;
- uart_ops串口的操作集,可能一个,也可能多个;
同时需要调用的API有: - uart_register_driver,一次;
- uart_add_one_port,多次;