1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <robh@kernel.org>
5 #include <linux/kernel.h>
6 #include <linux/serdev.h>
8 #include <linux/tty_driver.h>
9 #include <linux/poll.h>
11 #define SERPORT_ACTIVE 1
14 struct tty_port
*port
;
15 struct tty_struct
*tty
;
16 struct tty_driver
*tty_drv
;
22 * Callback functions from the tty port.
25 static size_t ttyport_receive_buf(struct tty_port
*port
, const u8
*cp
,
26 const u8
*fp
, size_t count
)
28 struct serdev_controller
*ctrl
= port
->client_data
;
29 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
32 if (!test_bit(SERPORT_ACTIVE
, &serport
->flags
))
35 ret
= serdev_controller_receive_buf(ctrl
, cp
, count
);
37 dev_WARN_ONCE(&ctrl
->dev
, ret
> count
,
38 "receive_buf returns %zu (count = %zu)\n",
46 static void ttyport_write_wakeup(struct tty_port
*port
)
48 struct serdev_controller
*ctrl
= port
->client_data
;
49 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
50 struct tty_struct
*tty
;
52 tty
= tty_port_tty_get(port
);
56 if (test_and_clear_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
) &&
57 test_bit(SERPORT_ACTIVE
, &serport
->flags
))
58 serdev_controller_write_wakeup(ctrl
);
60 /* Wake up any tty_wait_until_sent() */
61 wake_up_interruptible(&tty
->write_wait
);
66 static const struct tty_port_client_operations client_ops
= {
67 .receive_buf
= ttyport_receive_buf
,
68 .write_wakeup
= ttyport_write_wakeup
,
72 * Callback functions from the serdev core.
75 static ssize_t
ttyport_write_buf(struct serdev_controller
*ctrl
, const u8
*data
, size_t len
)
77 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
78 struct tty_struct
*tty
= serport
->tty
;
80 if (!test_bit(SERPORT_ACTIVE
, &serport
->flags
))
83 set_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
);
84 return tty
->ops
->write(serport
->tty
, data
, len
);
87 static void ttyport_write_flush(struct serdev_controller
*ctrl
)
89 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
90 struct tty_struct
*tty
= serport
->tty
;
92 tty_driver_flush_buffer(tty
);
95 static int ttyport_write_room(struct serdev_controller
*ctrl
)
97 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
98 struct tty_struct
*tty
= serport
->tty
;
100 return tty_write_room(tty
);
103 static int ttyport_open(struct serdev_controller
*ctrl
)
105 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
106 struct tty_struct
*tty
;
107 struct ktermios ktermios
;
110 tty
= tty_init_dev(serport
->tty_drv
, serport
->tty_idx
);
115 if (!tty
->ops
->open
|| !tty
->ops
->close
) {
120 ret
= tty
->ops
->open(serport
->tty
, NULL
);
124 tty_unlock(serport
->tty
);
126 /* Bring the UART into a known 8 bits no parity hw fc state */
127 ktermios
= tty
->termios
;
128 ktermios
.c_iflag
&= ~(IGNBRK
| BRKINT
| PARMRK
| ISTRIP
|
129 INLCR
| IGNCR
| ICRNL
| IXON
);
130 ktermios
.c_oflag
&= ~OPOST
;
131 ktermios
.c_lflag
&= ~(ECHO
| ECHONL
| ICANON
| ISIG
| IEXTEN
);
132 ktermios
.c_cflag
&= ~(CSIZE
| PARENB
);
133 ktermios
.c_cflag
|= CS8
;
134 ktermios
.c_cflag
|= CRTSCTS
;
135 /* Hangups are not supported so make sure to ignore carrier detect. */
136 ktermios
.c_cflag
|= CLOCAL
;
137 tty_set_termios(tty
, &ktermios
);
139 set_bit(SERPORT_ACTIVE
, &serport
->flags
);
144 tty
->ops
->close(tty
, NULL
);
147 tty_release_struct(tty
, serport
->tty_idx
);
152 static void ttyport_close(struct serdev_controller
*ctrl
)
154 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
155 struct tty_struct
*tty
= serport
->tty
;
157 clear_bit(SERPORT_ACTIVE
, &serport
->flags
);
161 tty
->ops
->close(tty
, NULL
);
164 tty_release_struct(tty
, serport
->tty_idx
);
167 static unsigned int ttyport_set_baudrate(struct serdev_controller
*ctrl
, unsigned int speed
)
169 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
170 struct tty_struct
*tty
= serport
->tty
;
171 struct ktermios ktermios
= tty
->termios
;
173 ktermios
.c_cflag
&= ~CBAUD
;
174 tty_termios_encode_baud_rate(&ktermios
, speed
, speed
);
176 /* tty_set_termios() return not checked as it is always 0 */
177 tty_set_termios(tty
, &ktermios
);
178 return ktermios
.c_ospeed
;
181 static void ttyport_set_flow_control(struct serdev_controller
*ctrl
, bool enable
)
183 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
184 struct tty_struct
*tty
= serport
->tty
;
185 struct ktermios ktermios
= tty
->termios
;
188 ktermios
.c_cflag
|= CRTSCTS
;
190 ktermios
.c_cflag
&= ~CRTSCTS
;
192 tty_set_termios(tty
, &ktermios
);
195 static int ttyport_set_parity(struct serdev_controller
*ctrl
,
196 enum serdev_parity parity
)
198 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
199 struct tty_struct
*tty
= serport
->tty
;
200 struct ktermios ktermios
= tty
->termios
;
202 ktermios
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
203 if (parity
!= SERDEV_PARITY_NONE
) {
204 ktermios
.c_cflag
|= PARENB
;
205 if (parity
== SERDEV_PARITY_ODD
)
206 ktermios
.c_cflag
|= PARODD
;
209 tty_set_termios(tty
, &ktermios
);
211 if ((tty
->termios
.c_cflag
& (PARENB
| PARODD
| CMSPAR
)) !=
212 (ktermios
.c_cflag
& (PARENB
| PARODD
| CMSPAR
)))
218 static void ttyport_wait_until_sent(struct serdev_controller
*ctrl
, long timeout
)
220 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
221 struct tty_struct
*tty
= serport
->tty
;
223 tty_wait_until_sent(tty
, timeout
);
226 static int ttyport_get_tiocm(struct serdev_controller
*ctrl
)
228 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
229 struct tty_struct
*tty
= serport
->tty
;
231 if (!tty
->ops
->tiocmget
)
234 return tty
->ops
->tiocmget(tty
);
237 static int ttyport_set_tiocm(struct serdev_controller
*ctrl
, unsigned int set
, unsigned int clear
)
239 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
240 struct tty_struct
*tty
= serport
->tty
;
242 if (!tty
->ops
->tiocmset
)
245 return tty
->ops
->tiocmset(tty
, set
, clear
);
248 static int ttyport_break_ctl(struct serdev_controller
*ctrl
, unsigned int break_state
)
250 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
251 struct tty_struct
*tty
= serport
->tty
;
253 if (!tty
->ops
->break_ctl
)
256 return tty
->ops
->break_ctl(tty
, break_state
);
259 static const struct serdev_controller_ops ctrl_ops
= {
260 .write_buf
= ttyport_write_buf
,
261 .write_flush
= ttyport_write_flush
,
262 .write_room
= ttyport_write_room
,
263 .open
= ttyport_open
,
264 .close
= ttyport_close
,
265 .set_flow_control
= ttyport_set_flow_control
,
266 .set_parity
= ttyport_set_parity
,
267 .set_baudrate
= ttyport_set_baudrate
,
268 .wait_until_sent
= ttyport_wait_until_sent
,
269 .get_tiocm
= ttyport_get_tiocm
,
270 .set_tiocm
= ttyport_set_tiocm
,
271 .break_ctl
= ttyport_break_ctl
,
274 struct device
*serdev_tty_port_register(struct tty_port
*port
,
276 struct device
*parent
,
277 struct tty_driver
*drv
, int idx
)
279 struct serdev_controller
*ctrl
;
280 struct serport
*serport
;
283 if (!port
|| !drv
|| !parent
)
284 return ERR_PTR(-ENODEV
);
286 ctrl
= serdev_controller_alloc(host
, parent
, sizeof(struct serport
));
288 return ERR_PTR(-ENOMEM
);
289 serport
= serdev_controller_get_drvdata(ctrl
);
291 serport
->port
= port
;
292 serport
->tty_idx
= idx
;
293 serport
->tty_drv
= drv
;
295 ctrl
->ops
= &ctrl_ops
;
297 port
->client_ops
= &client_ops
;
298 port
->client_data
= ctrl
;
300 ret
= serdev_controller_add(ctrl
);
304 dev_info(&ctrl
->dev
, "tty port %s%d registered\n", drv
->name
, idx
);
308 port
->client_data
= NULL
;
309 port
->client_ops
= &tty_port_default_client_ops
;
310 serdev_controller_put(ctrl
);
315 int serdev_tty_port_unregister(struct tty_port
*port
)
317 struct serdev_controller
*ctrl
= port
->client_data
;
318 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
323 serdev_controller_remove(ctrl
);
324 port
->client_data
= NULL
;
325 port
->client_ops
= &tty_port_default_client_ops
;
326 serdev_controller_put(ctrl
);