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 int ttyport_receive_buf(struct tty_port
*port
, const unsigned char *cp
,
26 const unsigned char *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
< 0 || ret
> count
,
38 "receive_buf returns %d (count = %zu)\n",
48 static void ttyport_write_wakeup(struct tty_port
*port
)
50 struct serdev_controller
*ctrl
= port
->client_data
;
51 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
52 struct tty_struct
*tty
;
54 tty
= tty_port_tty_get(port
);
58 if (test_and_clear_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
) &&
59 test_bit(SERPORT_ACTIVE
, &serport
->flags
))
60 serdev_controller_write_wakeup(ctrl
);
62 /* Wake up any tty_wait_until_sent() */
63 wake_up_interruptible(&tty
->write_wait
);
68 static const struct tty_port_client_operations client_ops
= {
69 .receive_buf
= ttyport_receive_buf
,
70 .write_wakeup
= ttyport_write_wakeup
,
74 * Callback functions from the serdev core.
77 static int ttyport_write_buf(struct serdev_controller
*ctrl
, const unsigned char *data
, size_t len
)
79 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
80 struct tty_struct
*tty
= serport
->tty
;
82 if (!test_bit(SERPORT_ACTIVE
, &serport
->flags
))
85 set_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
);
86 return tty
->ops
->write(serport
->tty
, data
, len
);
89 static void ttyport_write_flush(struct serdev_controller
*ctrl
)
91 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
92 struct tty_struct
*tty
= serport
->tty
;
94 tty_driver_flush_buffer(tty
);
97 static int ttyport_write_room(struct serdev_controller
*ctrl
)
99 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
100 struct tty_struct
*tty
= serport
->tty
;
102 return tty_write_room(tty
);
105 static int ttyport_open(struct serdev_controller
*ctrl
)
107 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
108 struct tty_struct
*tty
;
109 struct ktermios ktermios
;
112 tty
= tty_init_dev(serport
->tty_drv
, serport
->tty_idx
);
117 if (!tty
->ops
->open
|| !tty
->ops
->close
) {
122 ret
= tty
->ops
->open(serport
->tty
, NULL
);
126 tty_unlock(serport
->tty
);
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 /* Hangups are not supported so make sure to ignore carrier detect. */
138 ktermios
.c_cflag
|= CLOCAL
;
139 tty_set_termios(tty
, &ktermios
);
141 set_bit(SERPORT_ACTIVE
, &serport
->flags
);
146 tty
->ops
->close(tty
, NULL
);
149 tty_release_struct(tty
, serport
->tty_idx
);
154 static void ttyport_close(struct serdev_controller
*ctrl
)
156 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
157 struct tty_struct
*tty
= serport
->tty
;
159 clear_bit(SERPORT_ACTIVE
, &serport
->flags
);
163 tty
->ops
->close(tty
, NULL
);
166 tty_release_struct(tty
, serport
->tty_idx
);
169 static unsigned int ttyport_set_baudrate(struct serdev_controller
*ctrl
, unsigned int speed
)
171 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
172 struct tty_struct
*tty
= serport
->tty
;
173 struct ktermios ktermios
= tty
->termios
;
175 ktermios
.c_cflag
&= ~CBAUD
;
176 tty_termios_encode_baud_rate(&ktermios
, speed
, speed
);
178 /* tty_set_termios() return not checked as it is always 0 */
179 tty_set_termios(tty
, &ktermios
);
180 return ktermios
.c_ospeed
;
183 static void ttyport_set_flow_control(struct serdev_controller
*ctrl
, bool enable
)
185 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
186 struct tty_struct
*tty
= serport
->tty
;
187 struct ktermios ktermios
= tty
->termios
;
190 ktermios
.c_cflag
|= CRTSCTS
;
192 ktermios
.c_cflag
&= ~CRTSCTS
;
194 tty_set_termios(tty
, &ktermios
);
197 static int ttyport_set_parity(struct serdev_controller
*ctrl
,
198 enum serdev_parity parity
)
200 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
201 struct tty_struct
*tty
= serport
->tty
;
202 struct ktermios ktermios
= tty
->termios
;
204 ktermios
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
205 if (parity
!= SERDEV_PARITY_NONE
) {
206 ktermios
.c_cflag
|= PARENB
;
207 if (parity
== SERDEV_PARITY_ODD
)
208 ktermios
.c_cflag
|= PARODD
;
211 tty_set_termios(tty
, &ktermios
);
213 if ((tty
->termios
.c_cflag
& (PARENB
| PARODD
| CMSPAR
)) !=
214 (ktermios
.c_cflag
& (PARENB
| PARODD
| CMSPAR
)))
220 static void ttyport_wait_until_sent(struct serdev_controller
*ctrl
, long timeout
)
222 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
223 struct tty_struct
*tty
= serport
->tty
;
225 tty_wait_until_sent(tty
, timeout
);
228 static int ttyport_get_tiocm(struct serdev_controller
*ctrl
)
230 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
231 struct tty_struct
*tty
= serport
->tty
;
233 if (!tty
->ops
->tiocmget
)
236 return tty
->ops
->tiocmget(tty
);
239 static int ttyport_set_tiocm(struct serdev_controller
*ctrl
, unsigned int set
, unsigned int clear
)
241 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
242 struct tty_struct
*tty
= serport
->tty
;
244 if (!tty
->ops
->tiocmset
)
247 return tty
->ops
->tiocmset(tty
, set
, clear
);
250 static const struct serdev_controller_ops ctrl_ops
= {
251 .write_buf
= ttyport_write_buf
,
252 .write_flush
= ttyport_write_flush
,
253 .write_room
= ttyport_write_room
,
254 .open
= ttyport_open
,
255 .close
= ttyport_close
,
256 .set_flow_control
= ttyport_set_flow_control
,
257 .set_parity
= ttyport_set_parity
,
258 .set_baudrate
= ttyport_set_baudrate
,
259 .wait_until_sent
= ttyport_wait_until_sent
,
260 .get_tiocm
= ttyport_get_tiocm
,
261 .set_tiocm
= ttyport_set_tiocm
,
264 struct device
*serdev_tty_port_register(struct tty_port
*port
,
265 struct device
*parent
,
266 struct tty_driver
*drv
, int idx
)
268 const struct tty_port_client_operations
*old_ops
;
269 struct serdev_controller
*ctrl
;
270 struct serport
*serport
;
273 if (!port
|| !drv
|| !parent
)
274 return ERR_PTR(-ENODEV
);
276 ctrl
= serdev_controller_alloc(parent
, sizeof(struct serport
));
278 return ERR_PTR(-ENOMEM
);
279 serport
= serdev_controller_get_drvdata(ctrl
);
281 serport
->port
= port
;
282 serport
->tty_idx
= idx
;
283 serport
->tty_drv
= drv
;
285 ctrl
->ops
= &ctrl_ops
;
287 old_ops
= port
->client_ops
;
288 port
->client_ops
= &client_ops
;
289 port
->client_data
= ctrl
;
291 ret
= serdev_controller_add(ctrl
);
295 dev_info(&ctrl
->dev
, "tty port %s%d registered\n", drv
->name
, idx
);
299 port
->client_data
= NULL
;
300 port
->client_ops
= old_ops
;
301 serdev_controller_put(ctrl
);
306 int serdev_tty_port_unregister(struct tty_port
*port
)
308 struct serdev_controller
*ctrl
= port
->client_data
;
309 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
314 serdev_controller_remove(ctrl
);
315 port
->client_ops
= NULL
;
316 port
->client_data
= NULL
;
317 serdev_controller_put(ctrl
);