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_interruptible_poll(&tty
->write_wait
, POLLOUT
);
67 static const struct tty_port_client_operations client_ops
= {
68 .receive_buf
= ttyport_receive_buf
,
69 .write_wakeup
= ttyport_write_wakeup
,
73 * Callback functions from the serdev core.
76 static int ttyport_write_buf(struct serdev_controller
*ctrl
, const unsigned char *data
, size_t len
)
78 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
79 struct tty_struct
*tty
= serport
->tty
;
81 if (!test_bit(SERPORT_ACTIVE
, &serport
->flags
))
84 set_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
);
85 return tty
->ops
->write(serport
->tty
, data
, len
);
88 static void ttyport_write_flush(struct serdev_controller
*ctrl
)
90 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
91 struct tty_struct
*tty
= serport
->tty
;
93 tty_driver_flush_buffer(tty
);
96 static int ttyport_write_room(struct serdev_controller
*ctrl
)
98 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
99 struct tty_struct
*tty
= serport
->tty
;
101 return tty_write_room(tty
);
104 static int ttyport_open(struct serdev_controller
*ctrl
)
106 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
107 struct tty_struct
*tty
;
108 struct ktermios ktermios
;
111 tty
= tty_init_dev(serport
->tty_drv
, serport
->tty_idx
);
116 if (!tty
->ops
->open
|| !tty
->ops
->close
) {
121 ret
= tty
->ops
->open(serport
->tty
, NULL
);
125 /* Bring the UART into a known 8 bits no parity hw fc state */
126 ktermios
= tty
->termios
;
127 ktermios
.c_iflag
&= ~(IGNBRK
| BRKINT
| PARMRK
| ISTRIP
|
128 INLCR
| IGNCR
| ICRNL
| IXON
);
129 ktermios
.c_oflag
&= ~OPOST
;
130 ktermios
.c_lflag
&= ~(ECHO
| ECHONL
| ICANON
| ISIG
| IEXTEN
);
131 ktermios
.c_cflag
&= ~(CSIZE
| PARENB
);
132 ktermios
.c_cflag
|= CS8
;
133 ktermios
.c_cflag
|= CRTSCTS
;
134 tty_set_termios(tty
, &ktermios
);
136 set_bit(SERPORT_ACTIVE
, &serport
->flags
);
138 tty_unlock(serport
->tty
);
142 tty
->ops
->close(tty
, NULL
);
145 tty_release_struct(tty
, serport
->tty_idx
);
150 static void ttyport_close(struct serdev_controller
*ctrl
)
152 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
153 struct tty_struct
*tty
= serport
->tty
;
155 clear_bit(SERPORT_ACTIVE
, &serport
->flags
);
159 tty
->ops
->close(tty
, NULL
);
162 tty_release_struct(tty
, serport
->tty_idx
);
165 static unsigned int ttyport_set_baudrate(struct serdev_controller
*ctrl
, unsigned int speed
)
167 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
168 struct tty_struct
*tty
= serport
->tty
;
169 struct ktermios ktermios
= tty
->termios
;
171 ktermios
.c_cflag
&= ~CBAUD
;
172 tty_termios_encode_baud_rate(&ktermios
, speed
, speed
);
174 /* tty_set_termios() return not checked as it is always 0 */
175 tty_set_termios(tty
, &ktermios
);
176 return ktermios
.c_ospeed
;
179 static void ttyport_set_flow_control(struct serdev_controller
*ctrl
, bool enable
)
181 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
182 struct tty_struct
*tty
= serport
->tty
;
183 struct ktermios ktermios
= tty
->termios
;
186 ktermios
.c_cflag
|= CRTSCTS
;
188 ktermios
.c_cflag
&= ~CRTSCTS
;
190 tty_set_termios(tty
, &ktermios
);
193 static void ttyport_wait_until_sent(struct serdev_controller
*ctrl
, long timeout
)
195 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
196 struct tty_struct
*tty
= serport
->tty
;
198 tty_wait_until_sent(tty
, timeout
);
201 static int ttyport_get_tiocm(struct serdev_controller
*ctrl
)
203 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
204 struct tty_struct
*tty
= serport
->tty
;
206 if (!tty
->ops
->tiocmget
)
209 return tty
->driver
->ops
->tiocmget(tty
);
212 static int ttyport_set_tiocm(struct serdev_controller
*ctrl
, unsigned int set
, unsigned int clear
)
214 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
215 struct tty_struct
*tty
= serport
->tty
;
217 if (!tty
->ops
->tiocmset
)
220 return tty
->driver
->ops
->tiocmset(tty
, set
, clear
);
223 static const struct serdev_controller_ops ctrl_ops
= {
224 .write_buf
= ttyport_write_buf
,
225 .write_flush
= ttyport_write_flush
,
226 .write_room
= ttyport_write_room
,
227 .open
= ttyport_open
,
228 .close
= ttyport_close
,
229 .set_flow_control
= ttyport_set_flow_control
,
230 .set_baudrate
= ttyport_set_baudrate
,
231 .wait_until_sent
= ttyport_wait_until_sent
,
232 .get_tiocm
= ttyport_get_tiocm
,
233 .set_tiocm
= ttyport_set_tiocm
,
236 struct device
*serdev_tty_port_register(struct tty_port
*port
,
237 struct device
*parent
,
238 struct tty_driver
*drv
, int idx
)
240 const struct tty_port_client_operations
*old_ops
;
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 old_ops
= port
->client_ops
;
260 port
->client_ops
= &client_ops
;
261 port
->client_data
= ctrl
;
263 ret
= serdev_controller_add(ctrl
);
267 dev_info(&ctrl
->dev
, "tty port %s%d registered\n", drv
->name
, idx
);
271 port
->client_data
= NULL
;
272 port
->client_ops
= old_ops
;
273 serdev_controller_put(ctrl
);
278 int serdev_tty_port_unregister(struct tty_port
*port
)
280 struct serdev_controller
*ctrl
= port
->client_data
;
281 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
286 serdev_controller_remove(ctrl
);
287 port
->client_ops
= NULL
;
288 port
->client_data
= NULL
;
289 serdev_controller_put(ctrl
);