1、
这段话摘于《设备驱动开发详解》
在使用串口核心层这个通用串口tty驱动层的接口后,一个串口驱动要完成的主要工作:
(1)、定义uart_driver、uart_ops、uart_port等结构体的实例并在适当的地方根据具体硬件和驱动的情况初始化它们,当然具体设备的驱动可以将这些结构体在新定义的xxx_uart_driver、xxx_uart_ops、xxx_uart_port之内。
(2)、在模块初始化是调用uart_register_driver和uart_add_port注册UART驱动并添加端口,在模块卸载时调用uart_unregister_driver和uart_remove_one_port以注销UART驱动并移除端口。
(3)、根据具体硬件的datasheet实现uart_ops中的成员函数,这些函数的实现成为UART驱动的主体工作。
2、s3c6410的串口驱动:
这些与上面的(1)相对应。
(1)、serial_core.c文件的作用:主要有如下结构体和实现其中的函数,供上层函数调用:
static const struct tty_operations uart_ops = {
.open = uart_open,
.close = uart_close,
.write = uart_write,
.put_char = uart_put_char,
.flush_chars = uart_flush_chars,
.write_room = uart_write_room,
.chars_in_buffer= uart_chars_in_buffer,
.flush_buffer = uart_flush_buffer,
.ioctl = uart_ioctl,
.throttle = uart_throttle,
.unthrottle = uart_unthrottle,
.send_xchar = uart_send_xchar,
.set_termios = uart_set_termios,
.set_ldisc = uart_set_ldisc,
.stop = uart_stop,
.start = uart_start,
.hangup = uart_hangup,
.break_ctl = uart_break_ctl,
.wait_until_sent= uart_wait_until_sent,
#ifdef CONFIG_PROC_FS
.read_proc = uart_read_proc,
#endif
.tiocmget = uart_tiocmget,
.tiocmset = uart_tiocmset,
#ifdef CONFIG_CONSOLE_POLL
.poll_init = uart_poll_init,
.poll_get_char= uart_poll_get_char,
.poll_put_char= uart_poll_put_char,
#endif
};
并提供uart_register_driver、uart_unregister_driver、uart_add_one_port、uart_remove_one_port函数供底层函数注册。
(2)、在sansung.c文件中有如下:
static struct uart_ops s3c24xx_serial_ops = {
.pm = s3c24xx_serial_pm,
.tx_empty = s3c24xx_serial_tx_empty,
.get_mctrl = s3c24xx_serial_get_mctrl,
.set_mctrl = s3c24xx_serial_set_mctrl,
.stop_tx = s3c24xx_serial_stop_tx,
.start_tx = s3c24xx_serial_start_tx,
.stop_rx = s3c24xx_serial_stop_rx,
.enable_ms = s3c24xx_serial_enable_ms,
.break_ctl = s3c24xx_serial_break_ctl,
.startup = s3c24xx_serial_startup,
.shutdown = s3c24xx_serial_shutdown,
.set_termios = s3c24xx_serial_set_termios,
.type = s3c24xx_serial_type,
.release_port = s3c24xx_serial_release_port,
.request_port = s3c24xx_serial_request_port,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
};
static struct uart_drivers3c24xx_uart_drv = {
.owner = THIS_MODULE,
.dev_name = "s3c2410_serial",
.nr = CONFIG_SERIAL_SAMSUNG_UARTS,
.cons = S3C24XX_SERIAL_CONSOLE,
.driver_name = S3C24XX_SERIAL_NAME,
.major = S3C24XX_SERIAL_MAJOR,
.minor = S3C24XX_SERIAL_MINOR,
};
原始结构为
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;
};
static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
[0] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX0,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 0,
}
},
[1] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX1,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 1,
}
},
#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
[2] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX2,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 2,
}
},
#endif
#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
[3] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX3,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
//---->modify by phantom
#if 1
.flags = UPF_BOOT_AUTOCONF | UPF_CONS_FLOW,
#else
.flags = UPF_BOOT_AUTOCONF,
#endif
//<----
.line = 3,
}
}
#endif
};
这个数组中的内容其实就是对下面struct uart_port结构成员的初始化。
其中: 结构体s3c24xx_uart_port源码如下:
struct s3c24xx_uart_port {
unsigned charrx_claimed;
unsigned chartx_claimed;
unsigned intpm_level;
unsigned longbaudclk_rate;
unsigned intrx_irq;
unsigned inttx_irq;
struct s3c24xx_uart_info*info;
struct s3c24xx_uart_clksrc*clksrc;
struct clk*clk;
struct clk*baudclk;
struct uart_portport;
#ifdef CONFIG_CPU_FREQ
struct notifier_blockfreq_transition;
#endif
};
其中:struct uart_port源码如下:
struct uart_port {
spinlock_tlock;/* port lock */
unsigned long iobase; /* in/out[bwl] */
unsigned char __iomem*membase;/* read/write[bwl] */
unsigned int irq; /* irq number */
unsigned intuartclk;/* base uart clock */
unsigned intfifosize;/* tx fifo size */
unsigned charx_char;/* xon/xoff char */
unsigned charregshift;/* reg offset shift */
unsigned chariotype;/* io access style */
unsigned charunused1;
#define UPIO_PORT(0)
#define UPIO_HUB6(1)
#define UPIO_MEM(2)
#define UPIO_MEM32(3)
#define UPIO_AU(4)/* Au1x00 type IO */
#define UPIO_TSI(5)/* Tsi108/109 type IO */
#define UPIO_DWAPB(6)/* DesignWare APB UART */
#define UPIO_RM9000(7)/* RM9000 type IO */
unsigned intread_status_mask;/* driver specific */
unsigned intignore_status_mask;/* driver specific */
struct uart_info*info;/* pointer to parent info */
struct uart_icounticount;/* statistics */
struct console*cons;/* struct console, if any */
#ifdef CONFIG_SERIAL_CORE_CONSOLE
unsigned longsysrq;/* sysrq timeout */
#endif
upf_tflags;
#define UPF_FOURPORT((__force upf_t) (1 << 1))
#define UPF_SAK((__force upf_t) (1 << 2))
#define UPF_SPD_MASK((__force upf_t) (0x1030))
#define UPF_SPD_HI((__force upf_t) (0x0010))
#define UPF_SPD_VHI((__force upf_t) (0x0020))
#define UPF_SPD_CUST((__force upf_t) (0x0030))
#define UPF_SPD_SHI((__force upf_t) (0x1000))
#define UPF_SPD_WARP((__force upf_t) (0x1010))
#define UPF_SKIP_TEST((__force upf_t) (1 << 6))
#define UPF_AUTO_IRQ((__force upf_t) (1 << 7))
#define UPF_HARDPPS_CD((__force upf_t) (1 << 11))
#define UPF_LOW_LATENCY((__force upf_t) (1 << 13))
#define UPF_BUGGY_UART((__force upf_t) (1 << 14))
#define UPF_MAGIC_MULTIPLIER((__force upf_t) (1 << 16))
#define UPF_CONS_FLOW((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ((__force upf_t) (1 << 24))
#define UPF_BOOT_AUTOCONF((__force upf_t) (1 << 28))
#define UPF_FIXED_PORT((__force upf_t) (1 << 29))
#define UPF_DEAD((__force upf_t) (1 << 30))
#define UPF_IOREMAP((__force upf_t) (1 << 31))
#define UPF_CHANGE_MASK((__force upf_t) (0x17fff))
#define UPF_USR_MASK((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
unsigned intmctrl;/* current modem ctrl settings */
unsigned inttimeout;/* character-based timeout */
unsigned inttype;/* port type */
const struct uart_ops*ops;
unsigned intcustom_divisor;
unsigned intline;/* port index */
resource_size_tmapbase;/* for ioremap */
struct device*dev;/* parent device */
unsigned charhub6;/* this should be in the 8250 driver */
unsigned charsuspended;
unsigned charunused[2];
void*private_data;/* generic platform data pointer */
};
s3c6410的UART设备驱动(2)的链接
s3c6410的UART设备驱动(3)的链接