2 * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <robh@kernel.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 #include <linux/kernel.h>
14 #include <linux/serdev.h>
15 #include <linux/tty.h>
16 #include <linux/tty_driver.h>
17 #include <linux/poll.h>
19 #define SERPORT_ACTIVE 1
22 struct tty_port *port;
23 struct tty_struct *tty;
24 struct tty_driver *tty_drv;
30 * Callback functions from the tty port.
33 static int ttyport_receive_buf(struct tty_port *port, const unsigned char *cp,
34 const unsigned char *fp, size_t count)
36 struct serdev_controller *ctrl = port->client_data;
37 struct serport *serport = serdev_controller_get_drvdata(ctrl);
40 if (!test_bit(SERPORT_ACTIVE, &serport->flags))
43 ret = serdev_controller_receive_buf(ctrl, cp, count);
45 dev_WARN_ONCE(&ctrl->dev, ret < 0 || ret > count,
46 "receive_buf returns %d (count = %zu)\n",
56 static void ttyport_write_wakeup(struct tty_port *port)
58 struct serdev_controller *ctrl = port->client_data;
59 struct serport *serport = serdev_controller_get_drvdata(ctrl);
60 struct tty_struct *tty;
62 tty = tty_port_tty_get(port);
66 if (test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
67 test_bit(SERPORT_ACTIVE, &serport->flags))
68 serdev_controller_write_wakeup(ctrl);
70 wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
75 static const struct tty_port_client_operations client_ops = {
76 .receive_buf = ttyport_receive_buf,
77 .write_wakeup = ttyport_write_wakeup,
81 * Callback functions from the serdev core.
84 static int ttyport_write_buf(struct serdev_controller *ctrl, const unsigned char *data, size_t len)
86 struct serport *serport = serdev_controller_get_drvdata(ctrl);
87 struct tty_struct *tty = serport->tty;
89 if (!test_bit(SERPORT_ACTIVE, &serport->flags))
92 set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
93 return tty->ops->write(serport->tty, data, len);
96 static void ttyport_write_flush(struct serdev_controller *ctrl)
98 struct serport *serport = serdev_controller_get_drvdata(ctrl);
99 struct tty_struct *tty = serport->tty;
101 tty_driver_flush_buffer(tty);
104 static int ttyport_write_room(struct serdev_controller *ctrl)
106 struct serport *serport = serdev_controller_get_drvdata(ctrl);
107 struct tty_struct *tty = serport->tty;
109 return tty_write_room(tty);
112 static int ttyport_open(struct serdev_controller *ctrl)
114 struct serport *serport = serdev_controller_get_drvdata(ctrl);
115 struct tty_struct *tty;
116 struct ktermios ktermios;
118 tty = tty_init_dev(serport->tty_drv, serport->tty_idx);
126 tty->ops->open(serport->tty, NULL);
128 /* Bring the UART into a known 8 bits no parity hw fc state */
129 ktermios = tty->termios;
130 ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
131 INLCR | IGNCR | ICRNL | IXON);
132 ktermios.c_oflag &= ~OPOST;
133 ktermios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
134 ktermios.c_cflag &= ~(CSIZE | PARENB);
135 ktermios.c_cflag |= CS8;
136 ktermios.c_cflag |= CRTSCTS;
137 tty_set_termios(tty, &ktermios);
139 set_bit(SERPORT_ACTIVE, &serport->flags);
141 tty_unlock(serport->tty);
146 tty_release_struct(tty, serport->tty_idx);
151 static void ttyport_close(struct serdev_controller *ctrl)
153 struct serport *serport = serdev_controller_get_drvdata(ctrl);
154 struct tty_struct *tty = serport->tty;
156 clear_bit(SERPORT_ACTIVE, &serport->flags);
160 tty->ops->close(tty, NULL);
163 tty_release_struct(tty, serport->tty_idx);
166 static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, unsigned int speed)
168 struct serport *serport = serdev_controller_get_drvdata(ctrl);
169 struct tty_struct *tty = serport->tty;
170 struct ktermios ktermios = tty->termios;
172 ktermios.c_cflag &= ~CBAUD;
173 tty_termios_encode_baud_rate(&ktermios, speed, speed);
175 /* tty_set_termios() return not checked as it is always 0 */
176 tty_set_termios(tty, &ktermios);
177 return ktermios.c_ospeed;
180 static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable)
182 struct serport *serport = serdev_controller_get_drvdata(ctrl);
183 struct tty_struct *tty = serport->tty;
184 struct ktermios ktermios = tty->termios;
187 ktermios.c_cflag |= CRTSCTS;
189 ktermios.c_cflag &= ~CRTSCTS;
191 tty_set_termios(tty, &ktermios);
194 static void ttyport_wait_until_sent(struct serdev_controller *ctrl, long timeout)
196 struct serport *serport = serdev_controller_get_drvdata(ctrl);
197 struct tty_struct *tty = serport->tty;
199 tty_wait_until_sent(tty, timeout);
202 static int ttyport_get_tiocm(struct serdev_controller *ctrl)
204 struct serport *serport = serdev_controller_get_drvdata(ctrl);
205 struct tty_struct *tty = serport->tty;
207 if (!tty->ops->tiocmget)
210 return tty->driver->ops->tiocmget(tty);
213 static int ttyport_set_tiocm(struct serdev_controller *ctrl, unsigned int set, unsigned int clear)
215 struct serport *serport = serdev_controller_get_drvdata(ctrl);
216 struct tty_struct *tty = serport->tty;
218 if (!tty->ops->tiocmset)
221 return tty->driver->ops->tiocmset(tty, set, clear);
224 static const struct serdev_controller_ops ctrl_ops = {
225 .write_buf = ttyport_write_buf,
226 .write_flush = ttyport_write_flush,
227 .write_room = ttyport_write_room,
228 .open = ttyport_open,
229 .close = ttyport_close,
230 .set_flow_control = ttyport_set_flow_control,
231 .set_baudrate = ttyport_set_baudrate,
232 .wait_until_sent = ttyport_wait_until_sent,
233 .get_tiocm = ttyport_get_tiocm,
234 .set_tiocm = ttyport_set_tiocm,
237 struct device *serdev_tty_port_register(struct tty_port *port,
238 struct device *parent,
239 struct tty_driver *drv, int idx)
241 struct serdev_controller *ctrl;
242 struct serport *serport;
245 if (!port || !drv || !parent)
246 return ERR_PTR(-ENODEV);
248 ctrl = serdev_controller_alloc(parent, sizeof(struct serport));
250 return ERR_PTR(-ENOMEM);
251 serport = serdev_controller_get_drvdata(ctrl);
253 serport->port = port;
254 serport->tty_idx = idx;
255 serport->tty_drv = drv;
257 ctrl->ops = &ctrl_ops;
259 port->client_ops = &client_ops;
260 port->client_data = ctrl;
262 ret = serdev_controller_add(ctrl);
266 dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx);
270 port->client_data = NULL;
271 port->client_ops = &tty_port_default_client_ops;
272 serdev_controller_put(ctrl);
277 int serdev_tty_port_unregister(struct tty_port *port)
279 struct serdev_controller *ctrl = port->client_data;
280 struct serport *serport = serdev_controller_get_drvdata(ctrl);
285 serdev_controller_remove(ctrl);
286 port->client_data = NULL;
287 port->client_ops = &tty_port_default_client_ops;
288 serdev_controller_put(ctrl);