一、串口驱动中的数据结构
尽管一个特定的UART设备驱动完全可以按照tty驱动的设计方法来设计,即定义tty_driver并实现tty_operations其中 的成员函数,但是Linux已经在文件serial_core.c中实现了UART设备的通用tty驱动层,称为串口核心层,这样,UART驱动的主要任 务变成了实现serial_core.c中定义的一组uart_xxx接口而非tty_xxx接口。
1.1下图描述了串行系统间的层次结构关系,可以概括为:
用户应用层 --> 线路规划层 --> TTY层 --> 底层驱动层 --> 物理硬件层
1.2下图是串口核心层在整个tty源文件关系及数据流向中的位置:
其中的xxx_uart.c在此处就是drivers/tty/serial/samsung.c和s3c6400.c
二、串口驱动中的数据结构
1.4使用到的数据结构
Uart驱动程序主要围绕三个关键的数据结构展开(include/linux/serial_core.h中定义):
- UART驱动程序结构:struct uart_driver
- UART端口结构: struct uart_port
- UART相关操作函数结构: struct uart_ops
1.4.1其中一个串口驱动对应一个struct uart_driver当然一个驱动是可以对应多个设备的:
1 struct uart_driver {
2 struct module *owner;
3 const char *driver_name;
4 const char *dev_name;
5 int major;
6 int minor;
7 int nr; //端口个数
8 struct console *cons;
9
10 /*
11 * these are private; the low level driver should not
12 * touch these; they should be initialised to NULL
13 */
14 struct uart_state *state;
15 struct tty_driver *tty_driver;
16 };
其中的uart_state是设备状态结构结构体:
1 struct uart_state {
2 struct tty_port port;
3 int pm_state;
4 struct circ_buf xmit;
5 struct tasklet_struct tlet;
6 struct uart_port *uart_port;
7 };
在uart_open()中:
tty->driver_data = state;
在其他uart_xxx()中:
struct uart_state *state = tty->driver_data;
就可以获取设备私有信息结构体。
1.4.2uart_port用于描述一个UART端口(直接对应于一个串口)的I/O端口或者IO内存地址等信息--->即一个uart_port对应一个端口
1 struct uart_port {
2 spinlock_t lock; /* port lock */
3 unsigned long iobase; /* in/out[bwl] */
4 unsigned char __iomem *membase; /* read/write[bwl] */
5 unsigned int (*serial_in)(struct uart_port *, int);
6 void (*serial_out)(struct uart_port *, int, int);
7 void (*set_termios)(struct uart_port *,
8 struct ktermios *new,
9 struct ktermios *old);
10 void (*pm)(struct uart_port *, unsigned int state,
11 unsigned int old);
12 unsigned int irq; /* irq number */
13 unsigned long irqflags; /* irq flags */
14 unsigned int uartclk; /* base uart clock */
15 unsigned int fifosize; /* tx fifo size */
16 unsigned char x_char; /* xon/xoff char */
17 unsigned char regshift; /* reg offset shift */
18 unsigned char iotype; /* io access style */
19 unsigned char unused1;
20
21 #define UPIO_PORT (0)
22 #define UPIO_HUB6 (1)
23 #define UPIO_MEM (2)
24 #define UPIO_MEM32 (3)
25 #define UPIO_AU (4) /* Au1x00 type IO */
26 #define UPIO_TSI (5) /* Tsi108/109 type IO */
27 #define UPIO_DWAPB (6) /* DesignWare APB UART */
28 #define UPIO_RM9000 (7) /* RM9000 type IO */
29 #define UPIO_DWAPB32 (8) /* DesignWare APB UART (32 bit accesses) */
30
31 unsigned int read_status_mask; /* driver specific */
32 unsigned int ignore_status_mask; /* driver specific */
33 struct uart_state *state; /* pointer to parent state */
34 struct uart_icount icount; /* statistics */
35
36 struct console *cons; /* struct console, if any */
37 #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)
38 unsigned long sysrq; /* sysrq timeout */
39 #endif
40
41 upf_t flags;
42
43 #define UPF_FOURPORT ((__force upf_t) (1 << 1))
44 #define UPF_SAK ((__force upf_t) (1 << 2))
45 #define UPF_SPD_MASK ((__force upf_t) (0x1030))
46 #define UPF_SPD_HI ((__force upf_t) (0x0010))
47 #define UPF_SPD_VHI ((__force upf_t) (0x0020))
48 #define UPF_SPD_CUST ((__force upf_t) (0x0030))
49 #define UPF_SPD_SHI ((__force upf_t) (0x1000))
50 #define UPF_SPD_WARP ((__force upf_t) (0x1010))
51 #define UPF_SKIP_TEST ((__force upf_t) (1 << 6))
52 #define UPF_AUTO_IRQ ((__force upf_t) (1 << 7))
53 #define UPF_HARDPPS_CD ((__force upf_t) (1 << 11))
54 #define UPF_LOW_LATENCY ((__force upf_t) (1 << 13))
55 #define UPF_BUGGY_UART ((__force upf_t) (1 << 14))
56 #define UPF_NO_TXEN_TEST ((__force upf_t) (1 << 15))
57 #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16))
58 #define UPF_CONS_FLOW ((__force upf_t) (1 << 23))
59 #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24))
60 /* The exact UART type is known and should not be probed. */
61 #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27))
62 #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28))
63 #define UPF_FIXED_PORT ((__force upf_t) (1 << 29))
64 #define UPF_DEAD ((__force upf_t) (1 << 30))
65 #define UPF_IOREMAP ((__force upf_t) (1 << 31))
66
67 #define UPF_CHANGE_MASK ((__force upf_t) (0x17fff))
68 #define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
69
70 unsigned int mctrl; /* current modem ctrl settings */
71 unsigned int timeout; /* character-based timeout */
72 unsigned int type; /* port type */
73 const struct uart_ops *ops;
74 unsigned int custom_divisor;
75 unsigned int line; /* port index */
76 resource_size_t mapbase; /* for ioremap */
77 struct device *dev; /* parent device */
78 unsigned char hub6; /* this should be in the 8250 driver */
79 unsigned char suspended;
80 unsigned char irq_wake;
81 unsigned char unused[2];
82 void *private_data; /* generic platform data pointer */
83 };
1.4.3uart_ops定义了针对UART的一系列操作
1 struct uart_ops {
2 unsigned int (*tx_empty)(struct uart_port *);
3 void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
4 unsigned int (*get_mctrl)(struct uart_port *);
5 void (*stop_tx)(struct uart_port *);
6 void (*start_tx)(struct uart_port *);
7 void (*send_xchar)(struct uart_port *, char ch);
8 void (*stop_rx)(struct uart_port *);
9 void (*enable_ms)(struct uart_port *);
10 void (*break_ctl)(struct uart_port *, int ctl);
11 int (*startup)(struct uart_port *);
12 void (*shutdown)(struct uart_port *);
13 void (*flush_buffer)(struct uart_port *);
14 void (*set_termios)(struct uart_port *, struct ktermios *new,
15 struct ktermios *old);
16 void (*set_ldisc)(struct uart_port *, int new);
17 void (*pm)(struct uart_port *, unsigned int state,
18 unsigned int oldstate);
19 int (*set_wake)(struct uart_port *, unsigned int state);
20
21 /*
22 * Return a string describing the type of the port
23 */
24 const char *(*type)(struct uart_port *);
25
26 /*
27 * Release IO and memory resources used by the port.
28 * This includes iounmap if necessary.
29 */
30 void (*release_port)(struct uart_port *);
31
32 /*
33 * Request IO and memory resources used by the port.
34 * This includes iomapping the port if necessary.
35 */
36 int (*request_port)(struct uart_port *);
37 void (*config_port)(struct uart_port *, int);
38 int (*verify_port)(struct uart_port *, struct serial_struct *);
39 int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
40 #ifdef CONFIG_CONSOLE_POLL
41 void (*poll_put_char)(struct uart_port *, unsigned char);
42 int (*poll_get_char)(struct uart_port *);
43 #endif
44 };
UART信息结构: struct uart_info
二、串口初始化分析
分析过程:
2.1进入到内核的Samsung.c文件中
找到内核模块加载函数:module_init(s3c24xx_serial_modinit);
可以看到加载模块直接调用platform_driver_register,注册了 开发板串口这个平台驱动。
因为把uart驱动注册为platform驱动,当平台驱动与平台设备进行匹配的时候会调用平台总线的match函数,匹配成功后就会调用平台驱动的xxx_probe()函数来进行一系列的初始化工作。
1 int s3c24xx_serial_probe(struct platform_device *dev,
2 struct s3c24xx_uart_info *info)
3 {
4 struct s3c24xx_uart_port *ourport;
5 int ret;
6
7 dbg("s3c24xx_serial_probe(%p, %p) %d
", dev, info, probe_index);
8
9 ourport = &s3c24xx_serial_ports[probe_index];
10 probe_index++;
11
12 dbg("%s: initialising port %p...
", __func__, ourport);
13
14 ret = s3c24xx_serial_init_port(ourport, info, dev);
15 if (ret < 0)
16 goto probe_err;
17
18 dbg("%s: adding port
", __func__);
19 uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
20 platform_set_drvdata(dev, &ourport->port);
21
22 ret = device_create_file(&dev->dev, &dev_attr_clock_source);
23 if (ret < 0)
24 printk(KERN_ERR "%s: failed to add clksrc attr.
", __func__);
25
26 ret = s3c24xx_serial_cpufreq_register(ourport);
27 if (ret < 0)
28 dev_err(&dev->dev, "failed to add cpufreq notifier
");
29
30 return 0;
31
32 probe_err:
33 return ret;
34 }