Writing a UART driver for Linux
Today we are going to write a UART driver for Linux!
UART (Universal asynchronous receiver-transmitter) is on of the most common device-to-device communication protocols that almost every SoC or microcontroller has hardware support for. Most SoC has several UART ports, but sometimes that is not enough as in this case.
Background
I'm working in a project where we have an ARM SoC connected to an FPGA on the AEMIF interface. This FPGA has implemented two UARTs that we intend to use from Linux. Unfortunately, I cannot share any more details about the platform nor the implementation in the FPGA, but that is not needed to understand the UART driver.
Since I can't reveal which client it is, I'll call the driver mfocserial.
Limitation
This driver comes with some limitations:
- The UART implementation does not have interrupts, so the driver will be polling only.
- No support for CONFIG_CONSOLE_POLL, so we will not be able to attach kgdb.
Overview of the driver
The FPGA is connected to the memory bus so driver will request_mem_region() and ioremap() the region to make it accessible for the device driver. The FPGA lack support for interrupts, so the device driver will setup a hrtimer for polling instead.
Here is an overview of the functions of the driver:
Lets go through the code.
Implementation
Global data
The driver initialize some global data structures:
1static struct uart_port mserial_ports[MSERIAL_NR_UARTS];
2static struct uart_driver mserial_uart_driver;
mserial_port is initialized as soon as a device is probed and mserial_uart_driver is statically defined further down:
1static struct uart_driver mserial_uart_driver = {
2 .owner = THIS_MODULE,
3 .driver_name = "mfocserial",
4 .dev_name = MSERIAL_NAME,
5 .major = MSERIAL_MAJOR,
6 .minor = MSERIAL_MINOR,
7 .nr = MSERIAL_NR_UARTS,
8};
The MSERIAL_NR_UARTS is set to 2 as we can see among the contants:
1#define PORT_MFOCSERIAL 0x57
2#define MSERIAL_NAME "ttyMFOC"
3#define MSERIAL_MAJOR 204
4#define MSERIAL_MINOR 187
5#define MSERIAL_NR_UARTS 2
6
7#define MSERIAL_POLLRATE (50000000)
8#define MSERIAL_CLOCK (12000000)
9#define MSERIAL_BR_MIN (MSERIAL_CLOCK / (8 * 0x3ff))
10#define MSERIAL_BR_MAX (MSERIAL_CLOCK / (8 * 0x001))
11
12#define UART_AUTOSUSPEND_TIMEOUT 3000 /* ms */
Initialization
Driver init
Since the FPGA is connected to the memory bus, we will register a platform driver:
1static struct platform_driver mserial_platform_driver = {
2 .probe = mserial_probe,
3 .remove = mserial_remove,
4 .driver = {
5 .name = "mfocserial",
6 .of_match_table = of_match_ptr(mserial_of_match),
7 },
8};
9
10static int __init mserial_init(void)
11{
12
13 pr_debug("mfocserial: calling platform_driver_register()\n");
14 return platform_driver_register(&mserial_platform_driver);
15}
16
17static void __exit mserial_exit(void)
18{
19 platform_driver_unregister(&mserial_platform_driver);
20 if (mserial_uart_driver.state)
21 uart_unregister_driver(&mserial_uart_driver);
22}
23
24module_init(mserial_init);
25module_exit(mserial_exit);
The mserial_probe will then be called for each registered device.
Device probe
The mserial_probe() function is invoked for each registred device. It is responsible for several things:
- Allocate all per-device data structures
- Fetch properties from the device tree (port-number and current-speed)
- Request the memory region to map
- Call mserial_assign() to map the device to the uart_port structure
1static int mserial_probe(struct platform_device *pdev)
2{
3 struct resource *res;
4 struct mserial_data *pdata;
5 int ret;
6 int id = pdev->id;
7
8 pdata = devm_kzalloc(&pdev->dev, sizeof(struct mserial_data),
9 GFP_KERNEL);
10 if (!pdata)
11 return -ENOMEM;
12
13 if (IS_ENABLED(CONFIG_OF)) {
14 const char *prop;
15 struct device_node *np = pdev->dev.of_node;
16
17 prop = "port-number";
18 ret = of_property_read_u32(np, prop, &id);
19 if (ret && ret != -EINVAL)
20of_err:
21 return dev_err_probe(&pdev->dev, ret,
22 "could not read %s\n", prop);
23
24 prop = "current-speed";
25 ret = of_property_read_u32(np, prop, &pdata->baud);
26 if (ret)
27 goto of_err;
28 } else {
29 pdata->baud = 9600;
30 pdata->cflags = CS8;
31 }
32
33 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
34 if (!res)
35 return -ENODEV;
36
37 if (!mserial_uart_driver.state) {
38 dev_dbg(&pdev->dev, "mfocserial: calling uart_register_driver()\n");
39 ret = uart_register_driver(&mserial_uart_driver);
40 if (ret < 0) {
41 dev_err(&pdev->dev, "Failed to register driver\n");
42 return ret;
43 }
44 }
45
46 ret = mserial_assign(&pdev->dev, id, res->start, pdata);
47
48 return ret;
49}
The memory region we need to map is also provided by the device tree and is accessible from platform_get_resource().
mserial_assign() does a few things:
- Map the probing device to one of the statically allocated uart_ports (mserial_ports):
- Initialize the spinlock
- Initialize the hrtimer
- Initialize the uart_port
- Finally call uart_add_one_port()
1static int mserial_assign(struct device *dev, int id, phys_addr_t base,
2 struct mserial_data *pdata)
3{
4 struct uart_port *port;
5 int rc;
6
7 /* if id = -1; then scan for a free id and use that */
8 if (id < 0) {
9 for (id = 0; id < MSERIAL_NR_UARTS; id++)
10 if (mserial_ports[id].mapbase == 0)
11 break;
12 }
13 if (id < 0 || id >= MSERIAL_NR_UARTS) {
14 dev_err(dev, "%s%i too large\n", MSERIAL_NAME, id);
15 return -EINVAL;
16 }
17
18 if ((mserial_ports[id].mapbase) && (mserial_ports[id].mapbase != base)) {
19 dev_err(dev, "cannot assign to %s%i; it is already in use\n",
20 MSERIAL_NAME, id);
21 return -EBUSY;
22 }
23
24 port = &mserial_ports[id];
25
26 spin_lock_init(&port->lock);
27 port->fifosize = 16;
28 port->regshift = 2;
29 port->iotype = UPIO_MEM;
30 port->iobase = 1; /* mark port in use */
31 port->mapbase = base;
32 port->membase = NULL;
33 port->ops = &mserial_ops;
34 port->flags = UPF_BOOT_AUTOCONF;
35 port->dev = dev;
36 port->type = PORT_UNKNOWN;
37 port->line = id;
38 port->private_data = pdata;
39 pdata->port = port;
40
41 dev_set_drvdata(dev, port);
42
43 pdata->pollrate = ktime_set(0, MSERIAL_POLLRATE);
44 hrtimer_init(&pdata->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
45 pdata->timer.function = mserial_poll;
46
47 /* Register the port */
48 rc = uart_add_one_port(&mserial_uart_driver, port);
49 if (rc) {
50 dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc);
51 port->mapbase = 0;
52 dev_set_drvdata(dev, NULL);
53 return rc;
54 }
55
56 return 0;
57}
All uart_ports has a set of operations to meet the UART API. Those operations is abstracted as a set of callback functions declared in a uart_ops structure. The struct uart_ops we use in this driver is defined as follows:
1static const struct uart_ops mserial_ops = {
2 .tx_empty = mserial_tx_empty,
3 .set_mctrl = mserial_set_mctrl,
4 .get_mctrl = mserial_get_mctrl,
5 .stop_tx = mserial_stop_tx,
6 .start_tx = mserial_start_tx,
7 .stop_rx = mserial_stop_rx,
8 .break_ctl = mserial_break_ctl,
9 .startup = mserial_startup,
10 .shutdown = mserial_shutdown,
11 .set_termios = mserial_set_termios,
12 .type = mserial_type,
13 .release_port = mserial_release_port,
14 .request_port = mserial_request_port,
15 .config_port = mserial_config_port,
16 .verify_port = mserial_verify_port,
17};
uart_add_one_port() allows the driver to register its own uart_port structure within the core layer.
UART operations
Lets take another look at the uart_ops structure. It contains a bunch of callback functions:
1static const struct uart_ops mserial_ops = {
2 .tx_empty = mserial_tx_empty,
3 .set_mctrl = mserial_set_mctrl,
4 .get_mctrl = mserial_get_mctrl,
5 .stop_tx = mserial_stop_tx,
6 .start_tx = mserial_start_tx,
7 .stop_rx = mserial_stop_rx,
8 .break_ctl = mserial_break_ctl,
9 .startup = mserial_startup,
10 .shutdown = mserial_shutdown,
11 .set_termios = mserial_set_termios,
12 .type = mserial_type,
13 .release_port = mserial_release_port,
14 .request_port = mserial_request_port,
15 .config_port = mserial_config_port,
16 .verify_port = mserial_verify_port,
17};
You will find a description of each callback function in the linux tree [1].
tx_empty
This function tests whether the transmitter fifo and shifter for the port is empty. If it is empty, this function should return TIOCSER_TEMT, otherwise return 0. If the port does not support this operation, then it should return TIOCSER_TEMT.
1static unsigned int mserial_tx_empty(struct uart_port *port)
2{
3 unsigned long flags;
4 unsigned int ret;
5
6 spin_lock_irqsave(&port->lock, flags);
7 ret = ioread32(port->membase + MSERIAL_CONSTAT);
8 spin_unlock_irqrestore(&port->lock, flags);
9
10 return (ret & MSERIAL_CONSTAT_TXC) ? TIOCSER_TEMT : 0;
11}
set_mctrl
This function sets the modem control lines for port to the state described by mctrl. The relevant bits of mctrl are:
- TIOCM_RTS RTS signal.
- TIOCM_DTR DTR signal.
- TIOCM_OUT1 OUT1 signal.
- TIOCM_OUT2 OUT2 signal.
- TIOCM_LOOP Set the port into loopback mode.
If the appropriate bit is set, the signal should be driven active. If the bit is clear, the signal should be driven inactive.
This driver does not implement the feature to set these control lines, so the implementation is simply:
1static void mserial_set_mctrl(struct uart_port *port, unsigned int mctrl)
2{
3 /* N/A */
4}
get_mctrl
Returns the current state of modem control inputs of @port. The state of the outputs should not be returned, since the core keeps track of their state. The state information should include:
- TIOCM_CAR state of DCD signal
- TIOCM_CTS state of CTS signal
- TIOCM_DSR state of DSR signal
- TIOCM_RI state of RI signal
The bit is set if the signal is currently driven active. If the port does not support CTS, DCD or DSR, the driver should indicate that the signal is permanently active. If RI is not available, the signal should not be indicated as active.
1static unsigned int mserial_get_mctrl(struct uart_port *port)
2{
3 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
4}
stop_tx
Stop transmitting characters. This might be due to the CTS line becoming inactive or the tty layer indicating we want to stop transmission due to an XOFF character.
The driver should stop transmitting characters as soon as possible.
We don't need to do any special for stop transmitting characters:
1static void mserial_stop_tx(struct uart_port *port)
2{
3}
start_tx
Start transmitting characters.
This function only calls mserial_transmit():
1static void mserial_start_tx(struct uart_port *port)
2{
3 mserial_transmit(port, ioread32(port->membase + MSERIAL_CONSTAT));
4}
For handling the transmitting of bytes from the circular buffer.
1static int mserial_transmit(struct uart_port *port, int stat)
2{
3 struct circ_buf *xmit = &port->state->xmit;
4
5 if (stat & MSERIAL_CONSTAT_TXFULL)
6 return 0;
7
8
9 if (port->x_char) {
10 iowrite8(port->x_char, port->membase + MSERIAL_TXDATA);
11 port->x_char = 0;
12 port->icount.tx++;
13 return 1;
14 }
15
16 if (uart_circ_empty(xmit) || uart_tx_stopped(port))
17 return 0;
18
19 iowrite8(xmit->buf[xmit->tail], port->membase + MSERIAL_TXDATA);
20 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
21 port->icount.tx++;
22
23 /* wake up */
24 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
25 uart_write_wakeup(port);
26
27 return 1;
28}
The uart_write_wakeup() routine is used by the interrupt handler to schedule processing in the software interrupt portion of the driver. The driver should call the function when the number of charactes in the transmit buffer have dropped below a threshold.
stop_rx
Stop receiving characters; the port is in the process of being closed.
1static void mserial_stop_rx(struct uart_port *port)
2{
3 /* don't forward any more data (like !CREAD) */
4 port->ignore_status_mask = MSERIAL_CONSTAT_ERRMASK;
5}
break_ctl
Control the transmission of a break signal. If ctl is nonzero, the break signal should be transmitted. The signal should be terminated when another call is made with a zero ctl.
1static void mserial_break_ctl(struct uart_port *port, int ctl)
2{
3 /* N/A */
4}
startup
Grab any interrupt resources and initialise any low level driver state. Enable the port for reception. This method will only be called when the port is initially opened.
As we are using a hrtimer to poll for rx data, it is not time to start the timer.
1static int mserial_startup(struct uart_port *port)
2{
3 struct mserial_data *pdata = port->private_data;
4
5 hrtimer_start(&pdata->timer, pdata->pollrate, HRTIMER_MODE_REL);
6
7 iowrite32(ioread32(port->membase + MSERIAL_CONSTAT) | MSERIAL_CONSTAT_ENUART,
8 port->membase + MSERIAL_CONSTAT);
9 return 0;
10}
Speaking of the timer. The timer function that kicks in is mserial_poll():
1static enum hrtimer_restart mserial_poll(struct hrtimer *timer)
2{
3 struct mserial_data *ss = container_of(timer, struct mserial_data, timer);
4 struct uart_port *port = ss->port;
5 int rx_or_tx, n = 0;
6 u16 cs;
7
8 do {
9 cs = ioread32(port->membase + MSERIAL_CONSTAT);
10 iowrite32(cs & ~MSERIAL_CONSTAT_ERRMASK, port->membase + MSERIAL_CONSTAT);
11
12 rx_or_tx = mserial_receive(port, cs);
13 rx_or_tx |= mserial_transmit(port, cs);
14 n++;
15 } while (rx_or_tx);
16
17 if (n > 1)
18 tty_flip_buffer_push(&port->state->port);
19
20 hrtimer_start(&ss->timer, ss->pollrate, HRTIMER_MODE_REL);
21 return HRTIMER_NORESTART;
22}
tty_flip_buffer_push() queues a push of the terminal flip buffer to the line current line discipline.
shutdown
Disable the port, disable any break condition that may be in effect, and free any interrupt resources.
Disable the UART and cancel the timer.
1static int mserial_startup(struct uart_port *port)
2{
3 struct mserial_data *pdata = port->private_data;
4
5 hrtimer_start(&pdata->timer, pdata->pollrate, HRTIMER_MODE_REL);
6
7 iowrite32(ioread32(port->membase + MSERIAL_CONSTAT) | MSERIAL_CONSTAT_ENUART,
8 port->membase + MSERIAL_CONSTAT);
9 return 0;
10}
set_termios
Change the port parameters, including word length, parity, stop bits. Update port->read_status_mask and port->ignore_status_mask to indicate the types of events we are interested in receiving.
The UART implementation in the FPGA is rather simple and does not allow any port parameters except baudrate.
1static void mserial_set_termios(struct uart_port *port,
2 struct ktermios *termios,
3 const struct ktermios *old)
4{
5 unsigned long flags;
6 unsigned int baud = 0;
7 u16 div;
8
9 spin_lock_irqsave(&port->lock, flags);
10
11 baud = uart_get_baud_rate(
12 port, termios, old, MSERIAL_BR_MIN, MSERIAL_BR_MAX);
13
14 if (baud) {
15 div = MSERIAL_CLOCK / (8 * baud);
16 iowrite32(div, port->membase + MSERIAL_BR);
17 uart_update_timeout(port, termios->c_cflag, baud);
18 }
19 spin_unlock_irqrestore(&port->lock, flags);
20
21}
type
Return a pointer to a string constant describing the specified port, or return NULL, in which case the string 'unknown' is substituted.
1static const char *mserial_type(struct uart_port *port)
2{
3 return port->type == PORT_MFOCSERIAL ? "mfocserial" : NULL;
4}
release_port
Release any memory and IO region resources currently in use by the port.
In our case we only have the memory region to release.
1static void mserial_release_port(struct uart_port *port)
2{
3 release_mem_region(port->mapbase, MSERIAL_REGION);
4 iounmap(port->membase);
5 port->membase = NULL;
6}
request_port
Request any memory and IO region resources required by the port. If any fail, no resources should be registered when this function returns, and it should return -EBUSY on failure.
1static int mserial_request_port(struct uart_port *port)
2{
3 pr_debug("mserial console: port=%p; port->mapbase=%llx\n",
4 port, (unsigned long long) port->mapbase);
5
6 if (!request_mem_region(port->mapbase, MSERIAL_REGION, "mserial")) {
7 dev_err(port->dev, "Memory region busy\n");
8 return -EBUSY;
9 }
10
11 port->membase = ioremap(port->mapbase, MSERIAL_REGION);
12 if (!port->membase) {
13 dev_err(port->dev, "Unable to map registers\n");
14 release_mem_region(port->mapbase, MSERIAL_REGION);
15 return -EBUSY;
16 }
17 return 0;
18}
config_port
Perform any autoconfiguration steps required for the port. type contains a bit mask of the required configuration. port->type should be set to the type found, or PORT_UNKNOWN if no port was detected.
1static void mserial_config_port(struct uart_port *port, int flags)
2{
3 if (!mserial_request_port(port))
4 port->type = PORT_MFOCSERIAL;
5}
Complete driver
This is what the driver looks like when you put it all together:
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * mfocserial.c: MFOC Serial port driver
4 *
5 * Copyright (C) 2024 Marcus Folkesson <marcus.folkesson@gmail.com>
6 */
7
8#include <linux/platform_device.h>
9#include <linux/module.h>
10#include <linux/bitfield.h>
11#include <linux/console.h>
12#include <linux/serial.h>
13#include <linux/serial_core.h>
14#include <linux/tty.h>
15#include <linux/tty_flip.h>
16#include <linux/delay.h>
17#include <linux/hrtimer.h>
18#include <linux/interrupt.h>
19#include <linux/init.h>
20#include <linux/io.h>
21#include <linux/iopoll.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/of_device.h>
25#include <linux/of_platform.h>
26#include <linux/pm_runtime.h>
27
28#define PORT_MFOCSERIAL 0x57
29#define MSERIAL_NAME "ttyMFOC"
30#define MSERIAL_MAJOR 204
31#define MSERIAL_MINOR 187
32#define MSERIAL_NR_UARTS 2
33
34#define MSERIAL_POLLRATE (50000000)
35#define MSERIAL_CLOCK (12000000)
36#define MSERIAL_BR_MIN (MSERIAL_CLOCK / (8 * 0x3ff))
37#define MSERIAL_BR_MAX (MSERIAL_CLOCK / (8 * 0x001))
38
39#define UART_AUTOSUSPEND_TIMEOUT 3000 /* ms */
40
41/* ---------------------------------------------------------------------
42 * Register definitions
43 */
44
45#define MSERIAL_REGION 10
46#define MSERIAL_CONSTAT 0x00
47#define MSERIAL_TXDATA 0x04
48#define MSERIAL_RXDATA 0x08
49#define MSERIAL_BR 0x0c
50
51#define MSERIAL_CONSTAT_ENUART 0x0001
52#define MSERIAL_CONSTAT_PAR 0x0002
53#define MSERIAL_CONSTAT_ODD 0x0004
54#define MSERIAL_CONSTAT_RXEMPTY 0x0100
55#define MSERIAL_CONSTAT_RXFULL 0x0200
56#define MSERIAL_CONSTAT_OVR 0x0800
57#define MSERIAL_CONSTAT_FERR 0x1000
58#define MSERIAL_CONSTAT_PARERR 0x2000
59#define MSERIAL_CONSTAT_TXFULL 0x4000
60#define MSERIAL_CONSTAT_TXC 0x8000
61#define MSERIAL_CONSTAT_ERRMASK \
62 (MSERIAL_CONSTAT_OVR | MSERIAL_CONSTAT_FERR | MSERIAL_CONSTAT_PARERR)
63
64
65struct mserial_data {
66 struct uart_port *port;
67 unsigned int baud;
68 tcflag_t cflags;
69 struct hrtimer timer;
70 ktime_t pollrate;
71};
72
73
74static struct uart_port mserial_ports[MSERIAL_NR_UARTS];
75static struct uart_driver mserial_uart_driver;
76
77/* ---------------------------------------------------------------------
78 * Core UART driver operations
79 */
80
81
82static int mserial_receive(struct uart_port *port, int stat)
83{
84 struct tty_port *tport = &port->state->port;
85 unsigned char ch = 0;
86 char flag = TTY_NORMAL;
87
88 if (!(stat & (MSERIAL_CONSTAT_OVR | MSERIAL_CONSTAT_FERR)) &&
89 (stat & MSERIAL_CONSTAT_RXEMPTY))
90 return 0;
91
92 if (!(stat & MSERIAL_CONSTAT_RXEMPTY)) {
93 port->icount.rx++;
94 ch = ioread8(port->membase + MSERIAL_RXDATA);
95 }
96
97 port->icount.parity += (stat & MSERIAL_CONSTAT_PARERR) ? 1 : 0;
98 port->icount.overrun += (stat & MSERIAL_CONSTAT_OVR) ? 1 : 0;
99 port->icount.frame += (stat & MSERIAL_CONSTAT_FERR) ? 1 : 0;
100
101 if (!(stat & MSERIAL_CONSTAT_RXEMPTY))
102 tty_insert_flip_char(tport, ch, flag);
103 if (stat & MSERIAL_CONSTAT_OVR)
104 tty_insert_flip_char(tport, 0, TTY_OVERRUN);
105 if (stat & MSERIAL_CONSTAT_FERR)
106 tty_insert_flip_char(tport, 0, TTY_FRAME);
107
108 return 1;
109}
110
111
112static int mserial_transmit(struct uart_port *port, int stat)
113{
114 struct circ_buf *xmit = &port->state->xmit;
115
116 if (stat & MSERIAL_CONSTAT_TXFULL)
117 return 0;
118
119
120 if (port->x_char) {
121 iowrite8(port->x_char, port->membase + MSERIAL_TXDATA);
122 port->x_char = 0;
123 port->icount.tx++;
124 return 1;
125 }
126
127 if (uart_circ_empty(xmit) || uart_tx_stopped(port))
128 return 0;
129
130 iowrite8(xmit->buf[xmit->tail], port->membase + MSERIAL_TXDATA);
131 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
132 port->icount.tx++;
133
134 /* wake up */
135 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
136 uart_write_wakeup(port);
137
138 return 1;
139}
140
141static enum hrtimer_restart mserial_poll(struct hrtimer *timer)
142{
143 struct mserial_data *ss = container_of(timer, struct mserial_data, timer);
144 struct uart_port *port = ss->port;
145 int rx_or_tx, n = 0;
146 u16 cs;
147
148 do {
149 cs = ioread32(port->membase + MSERIAL_CONSTAT);
150 iowrite32(cs & ~MSERIAL_CONSTAT_ERRMASK, port->membase + MSERIAL_CONSTAT);
151
152 rx_or_tx = mserial_receive(port, cs);
153 rx_or_tx |= mserial_transmit(port, cs);
154 n++;
155 } while (rx_or_tx);
156
157 if (n > 1)
158 tty_flip_buffer_push(&port->state->port);
159
160 hrtimer_start(&ss->timer, ss->pollrate, HRTIMER_MODE_REL);
161 return HRTIMER_NORESTART;
162}
163
164static unsigned int mserial_tx_empty(struct uart_port *port)
165{
166 unsigned long flags;
167 unsigned int ret;
168
169 spin_lock_irqsave(&port->lock, flags);
170 ret = ioread32(port->membase + MSERIAL_CONSTAT);
171 spin_unlock_irqrestore(&port->lock, flags);
172
173 return (ret & MSERIAL_CONSTAT_TXC) ? TIOCSER_TEMT : 0;
174}
175
176static unsigned int mserial_get_mctrl(struct uart_port *port)
177{
178 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
179}
180
181static void mserial_set_mctrl(struct uart_port *port, unsigned int mctrl)
182{
183 /* N/A */
184}
185
186static void mserial_stop_tx(struct uart_port *port)
187{
188}
189
190static void mserial_start_tx(struct uart_port *port)
191{
192 mserial_transmit(port, ioread32(port->membase + MSERIAL_CONSTAT));
193}
194
195static void mserial_stop_rx(struct uart_port *port)
196{
197 /* don't forward any more data (like !CREAD) */
198 port->ignore_status_mask = MSERIAL_CONSTAT_ERRMASK;
199}
200
201static void mserial_break_ctl(struct uart_port *port, int ctl)
202{
203 /* N/A */
204}
205
206static int mserial_startup(struct uart_port *port)
207{
208 struct mserial_data *pdata = port->private_data;
209
210 hrtimer_start(&pdata->timer, pdata->pollrate, HRTIMER_MODE_REL);
211
212 iowrite32(ioread32(port->membase + MSERIAL_CONSTAT) | MSERIAL_CONSTAT_ENUART,
213 port->membase + MSERIAL_CONSTAT);
214 return 0;
215}
216
217static void mserial_shutdown(struct uart_port *port)
218{
219 struct mserial_data *pdata = port->private_data;
220
221 iowrite32(ioread32(port->membase + MSERIAL_CONSTAT) & ~MSERIAL_CONSTAT_ENUART,
222 port->membase + MSERIAL_CONSTAT);
223
224 hrtimer_cancel(&pdata->timer);
225}
226
227static void mserial_set_termios(struct uart_port *port,
228 struct ktermios *termios,
229 const struct ktermios *old)
230{
231 unsigned long flags;
232 unsigned int baud = 0;
233 u16 div;
234
235 spin_lock_irqsave(&port->lock, flags);
236
237 baud = uart_get_baud_rate(
238 port, termios, old, MSERIAL_BR_MIN, MSERIAL_BR_MAX);
239
240 if (baud) {
241 div = MSERIAL_CLOCK / (8 * baud);
242 iowrite32(div, port->membase + MSERIAL_BR);
243 uart_update_timeout(port, termios->c_cflag, baud);
244 }
245 spin_unlock_irqrestore(&port->lock, flags);
246
247}
248
249static const char *mserial_type(struct uart_port *port)
250{
251 return port->type == PORT_MFOCSERIAL ? "mfocserial" : NULL;
252}
253
254static void mserial_release_port(struct uart_port *port)
255{
256 release_mem_region(port->mapbase, MSERIAL_REGION);
257 iounmap(port->membase);
258 port->membase = NULL;
259}
260
261static int mserial_request_port(struct uart_port *port)
262{
263 pr_debug("mserial console: port=%p; port->mapbase=%llx\n",
264 port, (unsigned long long) port->mapbase);
265
266 if (!request_mem_region(port->mapbase, MSERIAL_REGION, "mserial")) {
267 dev_err(port->dev, "Memory region busy\n");
268 return -EBUSY;
269 }
270
271 port->membase = ioremap(port->mapbase, MSERIAL_REGION);
272 if (!port->membase) {
273 dev_err(port->dev, "Unable to map registers\n");
274 release_mem_region(port->mapbase, MSERIAL_REGION);
275 return -EBUSY;
276 }
277 return 0;
278}
279
280static void mserial_config_port(struct uart_port *port, int flags)
281{
282 if (!mserial_request_port(port))
283 port->type = PORT_MFOCSERIAL;
284}
285
286static int mserial_verify_port(struct uart_port *port, struct serial_struct *ser)
287{
288 /* we don't want the core code to modify any port params */
289 return -EINVAL;
290}
291
292static const struct uart_ops mserial_ops = {
293 .tx_empty = mserial_tx_empty,
294 .set_mctrl = mserial_set_mctrl,
295 .get_mctrl = mserial_get_mctrl,
296 .stop_tx = mserial_stop_tx,
297 .start_tx = mserial_start_tx,
298 .stop_rx = mserial_stop_rx,
299 .break_ctl = mserial_break_ctl,
300 .startup = mserial_startup,
301 .shutdown = mserial_shutdown,
302 .set_termios = mserial_set_termios,
303 .type = mserial_type,
304 .release_port = mserial_release_port,
305 .request_port = mserial_request_port,
306 .config_port = mserial_config_port,
307 .verify_port = mserial_verify_port,
308};
309
310static struct uart_driver mserial_uart_driver = {
311 .owner = THIS_MODULE,
312 .driver_name = "mfocserial",
313 .dev_name = MSERIAL_NAME,
314 .major = MSERIAL_MAJOR,
315 .minor = MSERIAL_MINOR,
316 .nr = MSERIAL_NR_UARTS,
317};
318
319/* ---------------------------------------------------------------------
320 * Port assignment functions (mapping devices to uart_port structures)
321 */
322
323static int mserial_assign(struct device *dev, int id, phys_addr_t base,
324 struct mserial_data *pdata)
325{
326 struct uart_port *port;
327 int rc;
328
329 /* if id = -1; then scan for a free id and use that */
330 if (id < 0) {
331 for (id = 0; id < MSERIAL_NR_UARTS; id++)
332 if (mserial_ports[id].mapbase == 0)
333 break;
334 }
335 if (id < 0 || id >= MSERIAL_NR_UARTS) {
336 dev_err(dev, "%s%i too large\n", MSERIAL_NAME, id);
337 return -EINVAL;
338 }
339
340 if ((mserial_ports[id].mapbase) && (mserial_ports[id].mapbase != base)) {
341 dev_err(dev, "cannot assign to %s%i; it is already in use\n",
342 MSERIAL_NAME, id);
343 return -EBUSY;
344 }
345
346 port = &mserial_ports[id];
347
348 spin_lock_init(&port->lock);
349 port->fifosize = 16;
350 port->regshift = 2;
351 port->iotype = UPIO_MEM;
352 port->iobase = 1; /* mark port in use */
353 port->mapbase = base;
354 port->membase = NULL;
355 port->ops = &mserial_ops;
356 port->flags = UPF_BOOT_AUTOCONF;
357 port->dev = dev;
358 port->type = PORT_UNKNOWN;
359 port->line = id;
360 port->private_data = pdata;
361 pdata->port = port;
362
363 dev_set_drvdata(dev, port);
364
365 pdata->pollrate = ktime_set(0, MSERIAL_POLLRATE);
366 hrtimer_init(&pdata->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
367 pdata->timer.function = mserial_poll;
368
369 /* Register the port */
370 rc = uart_add_one_port(&mserial_uart_driver, port);
371 if (rc) {
372 dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc);
373 port->mapbase = 0;
374 dev_set_drvdata(dev, NULL);
375 return rc;
376 }
377
378 return 0;
379}
380
381static int mserial_release(struct device *dev)
382{
383 struct uart_port *port = dev_get_drvdata(dev);
384 int rc = 0;
385
386 if (port) {
387 rc = uart_remove_one_port(&mserial_uart_driver, port);
388 dev_set_drvdata(dev, NULL);
389 port->mapbase = 0;
390 }
391
392 return rc;
393}
394
395
396/* ---------------------------------------------------------------------
397 * Platform bus binding
398 */
399
400
401#if defined(CONFIG_OF)
402/* Match table for of_platform binding */
403static const struct of_device_id mserial_of_match[] = {
404 { .compatible = "mfoc,mfocserial", },
405 {}
406};
407MODULE_DEVICE_TABLE(of, mserial_of_match);
408#endif /* CONFIG_OF */
409
410static int mserial_probe(struct platform_device *pdev)
411{
412 struct resource *res;
413 struct mserial_data *pdata;
414 int ret;
415 int id = pdev->id;
416
417 pdata = devm_kzalloc(&pdev->dev, sizeof(struct mserial_data),
418 GFP_KERNEL);
419 if (!pdata)
420 return -ENOMEM;
421
422 if (IS_ENABLED(CONFIG_OF)) {
423 const char *prop;
424 struct device_node *np = pdev->dev.of_node;
425
426 prop = "port-number";
427 ret = of_property_read_u32(np, prop, &id);
428 if (ret && ret != -EINVAL)
429of_err:
430 return dev_err_probe(&pdev->dev, ret,
431 "could not read %s\n", prop);
432
433 prop = "current-speed";
434 ret = of_property_read_u32(np, prop, &pdata->baud);
435 if (ret)
436 goto of_err;
437 } else {
438 pdata->baud = 9600;
439 pdata->cflags = CS8;
440 }
441
442 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
443 if (!res)
444 return -ENODEV;
445
446 if (!mserial_uart_driver.state) {
447 dev_dbg(&pdev->dev, "mfocserial: calling uart_register_driver()\n");
448 ret = uart_register_driver(&mserial_uart_driver);
449 if (ret < 0) {
450 dev_err(&pdev->dev, "Failed to register driver\n");
451 return ret;
452 }
453 }
454
455 ret = mserial_assign(&pdev->dev, id, res->start, pdata);
456
457 return ret;
458}
459
460static int mserial_remove(struct platform_device *pdev)
461{
462 return mserial_release(&pdev->dev);
463}
464
465/* work with hotplug and coldplug */
466MODULE_ALIAS("platform:mfocserial");
467
468static struct platform_driver mserial_platform_driver = {
469 .probe = mserial_probe,
470 .remove = mserial_remove,
471 .driver = {
472 .name = "mfocserial",
473 .of_match_table = of_match_ptr(mserial_of_match),
474 },
475};
476
477static int __init mserial_init(void)
478{
479
480 pr_debug("mfocserial: calling platform_driver_register()\n");
481 return platform_driver_register(&mserial_platform_driver);
482}
483
484static void __exit mserial_exit(void)
485{
486 platform_driver_unregister(&mserial_platform_driver);
487 if (mserial_uart_driver.state)
488 uart_unregister_driver(&mserial_uart_driver);
489}
490
491module_init(mserial_init);
492module_exit(mserial_exit);
493
494MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>");
495MODULE_DESCRIPTION("MFOC Serial Driver");
496MODULE_LICENSE("GPL");
Device tree node
The corresponding devicetree node:
1 mfocserial@64000040 {
2 compatible = "mfoc,mfocserial";
3 reg = <0x64000040 0xf>;
4 port-number = <0>;
5 current-speed = <115200>;
6 status = "okay";
7 };
8 mfocserial@64000050 {
9 compatible = "mfoc,mfocserial";
10 reg = <0x64000050 0xf>;
11 port-number = <1>;
12 current-speed = <115200>;
13 status = "okay";
14 };
Summary
Writing a UART driver is not more complicated than anything else. The UART framework makes it a smooth ride. Line disciplines and such is handled on a overlying layer and the UART drivers only needs to handle the very basic I/O communication - as most device drivers do.