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
);
39 if (!test_bit(SERPORT_ACTIVE
, &serport
->flags
))
42 return serdev_controller_receive_buf(ctrl
, cp
, count
);
45 static void ttyport_write_wakeup(struct tty_port
*port
)
47 struct serdev_controller
*ctrl
= port
->client_data
;
48 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
50 if (test_and_clear_bit(TTY_DO_WRITE_WAKEUP
, &port
->tty
->flags
) &&
51 test_bit(SERPORT_ACTIVE
, &serport
->flags
))
52 serdev_controller_write_wakeup(ctrl
);
54 wake_up_interruptible_poll(&port
->tty
->write_wait
, POLLOUT
);
57 static const struct tty_port_client_operations client_ops
= {
58 .receive_buf
= ttyport_receive_buf
,
59 .write_wakeup
= ttyport_write_wakeup
,
63 * Callback functions from the serdev core.
66 static int ttyport_write_buf(struct serdev_controller
*ctrl
, const unsigned char *data
, size_t len
)
68 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
69 struct tty_struct
*tty
= serport
->tty
;
71 if (!test_bit(SERPORT_ACTIVE
, &serport
->flags
))
74 set_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
);
75 return tty
->ops
->write(serport
->tty
, data
, len
);
78 static void ttyport_write_flush(struct serdev_controller
*ctrl
)
80 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
81 struct tty_struct
*tty
= serport
->tty
;
83 tty_driver_flush_buffer(tty
);
86 static int ttyport_write_room(struct serdev_controller
*ctrl
)
88 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
89 struct tty_struct
*tty
= serport
->tty
;
91 return tty_write_room(tty
);
94 static int ttyport_open(struct serdev_controller
*ctrl
)
96 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
97 struct tty_struct
*tty
;
98 struct ktermios ktermios
;
100 tty
= tty_init_dev(serport
->tty_drv
, serport
->tty_idx
);
106 tty
->ops
->open(serport
->tty
, NULL
);
108 tty_port_open(serport
->port
, tty
, NULL
);
110 /* Bring the UART into a known 8 bits no parity hw fc state */
111 ktermios
= tty
->termios
;
112 ktermios
.c_iflag
&= ~(IGNBRK
| BRKINT
| PARMRK
| ISTRIP
|
113 INLCR
| IGNCR
| ICRNL
| IXON
);
114 ktermios
.c_oflag
&= ~OPOST
;
115 ktermios
.c_lflag
&= ~(ECHO
| ECHONL
| ICANON
| ISIG
| IEXTEN
);
116 ktermios
.c_cflag
&= ~(CSIZE
| PARENB
);
117 ktermios
.c_cflag
|= CS8
;
118 ktermios
.c_cflag
|= CRTSCTS
;
119 tty_set_termios(tty
, &ktermios
);
121 set_bit(SERPORT_ACTIVE
, &serport
->flags
);
123 tty_unlock(serport
->tty
);
127 static void ttyport_close(struct serdev_controller
*ctrl
)
129 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
130 struct tty_struct
*tty
= serport
->tty
;
132 clear_bit(SERPORT_ACTIVE
, &serport
->flags
);
135 tty
->ops
->close(tty
, NULL
);
137 tty_release_struct(tty
, serport
->tty_idx
);
140 static unsigned int ttyport_set_baudrate(struct serdev_controller
*ctrl
, unsigned int speed
)
142 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
143 struct tty_struct
*tty
= serport
->tty
;
144 struct ktermios ktermios
= tty
->termios
;
146 ktermios
.c_cflag
&= ~CBAUD
;
147 tty_termios_encode_baud_rate(&ktermios
, speed
, speed
);
149 /* tty_set_termios() return not checked as it is always 0 */
150 tty_set_termios(tty
, &ktermios
);
151 return ktermios
.c_ospeed
;
154 static void ttyport_set_flow_control(struct serdev_controller
*ctrl
, bool enable
)
156 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
157 struct tty_struct
*tty
= serport
->tty
;
158 struct ktermios ktermios
= tty
->termios
;
161 ktermios
.c_cflag
|= CRTSCTS
;
163 ktermios
.c_cflag
&= ~CRTSCTS
;
165 tty_set_termios(tty
, &ktermios
);
168 static void ttyport_wait_until_sent(struct serdev_controller
*ctrl
, long timeout
)
170 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
171 struct tty_struct
*tty
= serport
->tty
;
173 tty_wait_until_sent(tty
, timeout
);
176 static int ttyport_get_tiocm(struct serdev_controller
*ctrl
)
178 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
179 struct tty_struct
*tty
= serport
->tty
;
181 if (!tty
->ops
->tiocmget
)
184 return tty
->driver
->ops
->tiocmget(tty
);
187 static int ttyport_set_tiocm(struct serdev_controller
*ctrl
, unsigned int set
, unsigned int clear
)
189 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
190 struct tty_struct
*tty
= serport
->tty
;
192 if (!tty
->ops
->tiocmset
)
195 return tty
->driver
->ops
->tiocmset(tty
, set
, clear
);
198 static const struct serdev_controller_ops ctrl_ops
= {
199 .write_buf
= ttyport_write_buf
,
200 .write_flush
= ttyport_write_flush
,
201 .write_room
= ttyport_write_room
,
202 .open
= ttyport_open
,
203 .close
= ttyport_close
,
204 .set_flow_control
= ttyport_set_flow_control
,
205 .set_baudrate
= ttyport_set_baudrate
,
206 .wait_until_sent
= ttyport_wait_until_sent
,
207 .get_tiocm
= ttyport_get_tiocm
,
208 .set_tiocm
= ttyport_set_tiocm
,
211 struct device
*serdev_tty_port_register(struct tty_port
*port
,
212 struct device
*parent
,
213 struct tty_driver
*drv
, int idx
)
215 const struct tty_port_client_operations
*old_ops
;
216 struct serdev_controller
*ctrl
;
217 struct serport
*serport
;
220 if (!port
|| !drv
|| !parent
)
221 return ERR_PTR(-ENODEV
);
223 ctrl
= serdev_controller_alloc(parent
, sizeof(struct serport
));
225 return ERR_PTR(-ENOMEM
);
226 serport
= serdev_controller_get_drvdata(ctrl
);
228 serport
->port
= port
;
229 serport
->tty_idx
= idx
;
230 serport
->tty_drv
= drv
;
232 ctrl
->ops
= &ctrl_ops
;
234 old_ops
= port
->client_ops
;
235 port
->client_ops
= &client_ops
;
236 port
->client_data
= ctrl
;
238 ret
= serdev_controller_add(ctrl
);
242 dev_info(&ctrl
->dev
, "tty port %s%d registered\n", drv
->name
, idx
);
246 port
->client_data
= NULL
;
247 port
->client_ops
= old_ops
;
248 serdev_controller_put(ctrl
);
253 int serdev_tty_port_unregister(struct tty_port
*port
)
255 struct serdev_controller
*ctrl
= port
->client_data
;
256 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
261 serdev_controller_remove(ctrl
);
262 port
->client_ops
= NULL
;
263 port
->client_data
= NULL
;
264 serdev_controller_put(ctrl
);