Arm-linux s5pv210 UART Driver

Source: Internet
Author: User

Arm-linux s5pv210 UART Driver (3)----serial core layer, key structure, interface relationship

Although a specific UART device driver can be designed with a TTY-driven design, which defines Tty_driver and implements Tty_operations member functions, Linux is already in the file Serial_ The universal TTY drive layer of the UART device, called the core layer of the serial port, is implemented in core.c, so that the main task of the UART driver becomes a set of UART_XXX interfaces defined in the SERIAL_CORE.C rather than the Tty_xxx interface.

The UART device is another layer of encapsulation following the tty_driver. In fact, Uart_driver is the corresponding tty_driver. In its operation function, the operation is transferred to Uart_port. When writing, first put the data into a called CIRC_ BUF ring buffer. The uart_port then takes the data from the buffer and writes it to the serial device. When Uart_port receives data from the serial device, the device is placed in the buffer corresponding to line discipline. So, when the user writes the serial port driver , you only need to register a uart_driver. Its primary function is to define the device node number. The device's operations are then encapsulated in Uart_port. The driver engineer does not need to care about the upper level of the process, just according to the hardware specification will be the interface function in the Uart_port to complete.

1. Describes the hierarchical relationship between the serial system, can be summarized as: User application Layer--line planning layer-----TTY layer--------Physical hardware layer

2. Is the core layer of the serial port in the whole TTY source file relationship and data Flow location:

One of the xxx_uart.c here is drivers/serial/samsung.c and s5pv210.c.

3. Interface Relationship:

As can be seen from the interface diagram, the user's call to UART device operation is very simple,

File_operations = [Tty_ldisc_ops] = Tty_operations = UART Ops

Where Tty_ldisc_ops line procedures are not necessary, depending on whether the application layer settings use Ldisc to process data.

General diagram of the 4.UART drive:

The commonly used data structures for 5.uart drivers are shown below:

The 6.Uart driver is primarily built around three key data structures (defined in include/linux/serial_core.h):

UART-specific driver structure definition: struct uart_driver s3c24xx_uart_drv;

UART Port structure definition: struct S3c24xx_uart_port s3c24xx_serial_ports;

UART related operation function structure definition: struct uart_ops s3c24xx_serial_ops;

The "1" Uart_driver encapsulates the tty_driver so that the underlying UART driver does not care Tty_driver

struct Uart_driver {    struct module        *owner;    const char        *driver_name;    const char        *dev_name;    int             major;    int             minor;    int             nr;    struct console        *cons;    /     * * These is private, the low level driver should not     * touch these; they should is initialised to NULL     * /    struct uart_state    *state;    struct tty_driver    *tty_driver;};

The uart_state is the device private information structure,

In Uart_open ():

Tty->driver_data = State;

In other uart_xxx ():

struct Uart_state *state = tty->driver_data;

You can get the device private information structure.

S3c24xx_uart_drv= {      . Owner           =this_module,      . Dev_name      = "S3c2440_serial",  //Specific device name      . nr          =config_serial_samsung_uarts,  //defines several ports      . Cons             = S3c24xx_serial_console,  // Console interface       . driver_name  =s3c24xx_serial_name,  //serial port name: Ttysac      . Major            =s3c24xx_serial_ MAJOR,  //main device number      . Minor            =s3c24xx_serial_minor,//   secondary device number};

A TTY driver must register/unregister tty_driver, while a UART driver becomes a registration/logoff uart_driver, using the following interface:

int uart_register_driver (struct uart_driver *drv);

void Uart_unregister_driver (struct uart_driver *drv);

The "2" Uart_port is used to describe an I/O port or IO memory address for a UART port (directly corresponding to a serial port).

struct Uart_port {spinlock_t lock;            /* Port lock */unsigned long iobase;        /* IN/OUT[BWL] */unsigned char __iomem *membase;    /* READ/WRITE[BWL] */unsigned int (*serial_in) (struct uart_port *, int);    void (*serial_out) (struct uart_port *, int, int);            unsigned int IRQ;        /* IRQ Number */unsigned long irqflags;        /* IRQ Flags */unsigned int uartclk;        /* Base UART clock */unsigned int fifosize;            /* TX FIFO size */unsigned char x_char;        /* Xon/xoff char */unsigned char regshift;            /* Reg OFFSET Shift */unsigned char iotype; /* IO access style */unsigned char unused1; #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 int read_status_mask;    /* Driver specific */unsigned int ignore_status_mask;            /* Driver specific */struct uart_state *state;            /* Pointer to the parent state */struct Uart_icount icount;            /* Statistics */struct console *cons; /* struct console, if any */#if defined (config_serial_core_console) | |            Defined (SUPPORT_SYSRQ) unsigned long sysrq; /* SYSRQ Timeout */#endif upf_t flags; #define UPF_FOURPORT ((__force upf_t) (1 << 1)) #define Up        F_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 ((__FORC e 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 <<)) #define Upf_low_latency ((__force upf_t) (1 <<)) #define Upf_buggy_uart ((__force upf_t) (1 <<)) #define Upf_no_txen_test ((__force upf_t) (1 <<)) #define Upf_magic_multiplie        R ((__force upf_t) (1 <<)) #define Upf_cons_flow ((__force upf_t) (1 <<)) #define UPF_SHARE_IRQ  ((__force upf_t) (1 <<))/* The exact UART type is known and should not being probed.  */#define UPF_FIXED_TYPE ((__force upf_t) (1 <<)) #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << ) #define Upf_fixed_port ((__force upf_t) (1 <<)) #define Upf_dead ((__force upf_t) (1 << 3 0)) #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 int mctrl;        /* Current Modem CTRL settings */unsigned int timeout;            /* character-based Timeout */unsigned int type;    /* Port type */const struct UART_OPS *ops;//uart operation set-------> unsigned int custom_divisor;            unsigned int line;        /* Port index */resource_size_t mapbase;            /* for IOREMAP */struct device *dev;            /* Parent Device */unsigned char hub6;    /* This should is in the 8250 driver */unsigned char suspended;    unsigned char unused[2];        void *private_data; /* Generic platform data pointer */};

The S3c24xx_uart_port encapsulates the Uart_port:
struct S3c24xx_uart_port {    unsigned char            rx_claimed;    unsigned char            tx_claimed;    unsigned int            pm_level;    unsigned long            baudclk_rate;    unsigned int            rx_irq;    unsigned int            tx_irq;    struct S3c24xx_uart_info    *info;    struct S3C24XX_UART_CLKSRC    *clksrc;    struct CLK            *clk;    struct CLK            *baudclk;    struct Uart_port        port; #ifdef config_cpu_freq    struct notifier_block        freq_transition; #endif    int                Channelnum;};

static struct S3c24xx_uart_portS3c24xx_serial_ports[Config_serial_samsung_uarts] = {[0] = {//serial 0;. Port = {. Lock = __spin_lock_unlocked (s3c24xx _serial_ports[0].port.lock),. Iotype = Upio_mem,. IRQ = Irq_s3cuart_rx0,. u ARTCLK = 0,. fifosize = 16,Defines the FIFO buffer size. Ops = &s3c24xx_serial_ops,Serial port related operation function. flags = upf_boot_autoconf,. Line = 0,//Lines}}, [1] = {//serial 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_unlock            ED (S3c24xx_serial_ports[2].port.lock),. Iotype = Upio_mem,. IRQ = Irq_s3cuart_rx2,         . UARTCLK = 0,. fifosize = +,. 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 = +,. Ops =  &s3c24xx_serial_ops,. Flags = upf_boot_autoconf,. Line = 3,}} #endif};

In Xxx_probe ():

The struct S3c24xx_uart_port *ourport;//s3c24xx_uart_port encapsulates uart_portourport = &s3c24xx_serial_ports[dev->id];/ /s3c24xx_serial_ports is a type of s3c24xx_uart_port structure.

The "3" Uart_ops defines a series of operations for the UART,

/* * This structure describes all the operations so can be * do on the physical hardware.    */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 (*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 *); void (*PM) (struct uart_port *, unsigned int state, unsigned int oLdstate);    Int (*set_wake) (struct uart_port *, unsigned int state);    void (*wake_peer) (struct uart_port *);    /* * 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 void (*poll_put_char    ) (struct Uart_port *, unsigned char); Int (*poll_get_char) (struct uart_port *); #endif};

In general, implementing the following member function is the main work of the UART driver
static struct Uart_opsS3c24xx_serial_ops={. PM =S3C24XX_SERIAL_PM,//power management function. Tx_empty = S3c24xx_serial_tx_empty,///check car send FIFO buffer is empty. Get_mctrl = S3c24xx_serial_get_mctrl,//whether the serial port flow control. Set_mctrl = S3c24xx_serial_set_mctrl,//whether to set serial port flow control CTS . Stop_tx =s3c24xx_serial_stop_tx,//stop sending. START_TX =s3c24xx_serial_start_tx,//start sending. STOP_RX =s3c24xx _SERIAL_STOP_RX,//stop receiving. Enable_ms = S3c24xx_serial_enable_ms,//null function. Break_ctl = S3c24xx_serial_bre Ak_ctl,//Send a break signal. Startup =s3c24xx_serial_startup,//serial port Send/Receive, and interrupt request initial configuration function. Shutdown = s3c24xx_s Erial_shutdown,//Turn off the serial port. Set_termios = s3c24xx_serial_set_termios,//serial port CLK, baud rate, data bits and other parameters set. Type = S3 C24xx_serial_type,//CPU type about the serial port. Release_port =s3c24xx_serial_release_port,//release serial. Request_port =s3c24x X_serial_request_port,//apply for serial port. Config_port = S3c24xx_serial_config_port,//serial port configuration information info. Verify_port = s 3c24xx_serial_verify_porT,//serial port detection. Wake_peer = S3c24xx_serial_wake_peer,};

In Serial_core.c, an instance of tty_operations is defined, including Uart_open (), Uart_close (), Uart_send_xchar (), and other member functions, which use Uart_ The member function in the OPS struct to accomplish the specific operation.

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_ro    Om,. 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,. Ha Ngup = Uart_hangup,. Break_ctl = Uart_break_ctl,. wait_until_sent= uart_wait_until_sent, #ifdef CONFIG_PROC _fs. Proc_fops = &uart_proc_fops, #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 = u Art_poll_put_char, #endif}; 

From the following example, we can see the relationship between the tty_operations and uart_ops of the core layer of the serial port:

/* * This function was used to send a high-priority xon/xoff character to * the device */static void Uart_send_xchar (struct Tty_struct *tty, Char ch) {    struct uart_state *state = tty->driver_data;    struct Uart_port *port = state->uart_port;    unsigned long flags;    if (Port->ops->send_xchar)/* If the Send_xchar member function is implemented in Uart_ops *        /Port->ops->send_xchar (port, ch);    else {        Port->x_char = ch;        if (CH) {            spin_lock_irqsave (&port->lock, flags);            PORT->OPS->START_TX (port);            Spin_unlock_irqrestore (&port->lock, Flags);}}}    

The invocation relationship for this example is as follows:

Send_xchar  ---->  uart_send_xchar---->  start_tx  --->  s3c24xx_serial_start_tx

Arm-linux s5pv210 UART Drive (RPM)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.