1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * UART driver for the Greybus "generic" UART module. |
4 | * |
5 | * Copyright 2014 Google Inc. |
6 | * Copyright 2014 Linaro Ltd. |
7 | * |
8 | * Heavily based on drivers/usb/class/cdc-acm.c and |
9 | * drivers/usb/serial/usb-serial.c. |
10 | */ |
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
12 | |
13 | #include <linux/kernel.h> |
14 | #include <linux/errno.h> |
15 | #include <linux/module.h> |
16 | #include <linux/sched/signal.h> |
17 | #include <linux/wait.h> |
18 | #include <linux/slab.h> |
19 | #include <linux/uaccess.h> |
20 | #include <linux/mutex.h> |
21 | #include <linux/tty.h> |
22 | #include <linux/serial.h> |
23 | #include <linux/tty_driver.h> |
24 | #include <linux/tty_flip.h> |
25 | #include <linux/idr.h> |
26 | #include <linux/fs.h> |
27 | #include <linux/kdev_t.h> |
28 | #include <linux/kfifo.h> |
29 | #include <linux/workqueue.h> |
30 | #include <linux/completion.h> |
31 | #include <linux/greybus.h> |
32 | |
33 | #include "gbphy.h" |
34 | |
35 | #define GB_NUM_MINORS 16 /* 16 is more than enough */ |
36 | #define GB_NAME "ttyGB" |
37 | |
38 | #define GB_UART_WRITE_FIFO_SIZE PAGE_SIZE |
39 | #define GB_UART_WRITE_ROOM_MARGIN 1 /* leave some space in fifo */ |
40 | #define GB_UART_FIRMWARE_CREDITS 4096 |
41 | #define GB_UART_CREDIT_WAIT_TIMEOUT_MSEC 10000 |
42 | |
43 | struct gb_tty { |
44 | struct gbphy_device *gbphy_dev; |
45 | struct tty_port port; |
46 | void *buffer; |
47 | size_t buffer_payload_max; |
48 | struct gb_connection *connection; |
49 | u16 cport_id; |
50 | unsigned int minor; |
51 | unsigned char clocal; |
52 | bool disconnected; |
53 | spinlock_t read_lock; |
54 | spinlock_t write_lock; |
55 | struct async_icount iocount; |
56 | struct async_icount oldcount; |
57 | wait_queue_head_t wioctl; |
58 | struct mutex mutex; |
59 | u8 ctrlin; /* input control lines */ |
60 | u8 ctrlout; /* output control lines */ |
61 | struct gb_uart_set_line_coding_request line_coding; |
62 | struct work_struct tx_work; |
63 | struct kfifo write_fifo; |
64 | bool close_pending; |
65 | unsigned int credits; |
66 | struct completion credits_complete; |
67 | }; |
68 | |
69 | static struct tty_driver *gb_tty_driver; |
70 | static DEFINE_IDR(tty_minors); |
71 | static DEFINE_MUTEX(table_lock); |
72 | |
73 | static int gb_uart_receive_data_handler(struct gb_operation *op) |
74 | { |
75 | struct gb_connection *connection = op->connection; |
76 | struct gb_tty *gb_tty = gb_connection_get_data(connection); |
77 | struct tty_port *port = &gb_tty->port; |
78 | struct gb_message *request = op->request; |
79 | struct gb_uart_recv_data_request *receive_data; |
80 | u16 recv_data_size; |
81 | int count; |
82 | unsigned long tty_flags = TTY_NORMAL; |
83 | |
84 | if (request->payload_size < sizeof(*receive_data)) { |
85 | dev_err(&gb_tty->gbphy_dev->dev, |
86 | "short receive-data request received (%zu < %zu)\n" , |
87 | request->payload_size, sizeof(*receive_data)); |
88 | return -EINVAL; |
89 | } |
90 | |
91 | receive_data = op->request->payload; |
92 | recv_data_size = le16_to_cpu(receive_data->size); |
93 | |
94 | if (recv_data_size != request->payload_size - sizeof(*receive_data)) { |
95 | dev_err(&gb_tty->gbphy_dev->dev, |
96 | "malformed receive-data request received (%u != %zu)\n" , |
97 | recv_data_size, |
98 | request->payload_size - sizeof(*receive_data)); |
99 | return -EINVAL; |
100 | } |
101 | |
102 | if (!recv_data_size) |
103 | return -EINVAL; |
104 | |
105 | if (receive_data->flags) { |
106 | if (receive_data->flags & GB_UART_RECV_FLAG_BREAK) |
107 | tty_flags = TTY_BREAK; |
108 | else if (receive_data->flags & GB_UART_RECV_FLAG_PARITY) |
109 | tty_flags = TTY_PARITY; |
110 | else if (receive_data->flags & GB_UART_RECV_FLAG_FRAMING) |
111 | tty_flags = TTY_FRAME; |
112 | |
113 | /* overrun is special, not associated with a char */ |
114 | if (receive_data->flags & GB_UART_RECV_FLAG_OVERRUN) |
115 | tty_insert_flip_char(port, ch: 0, TTY_OVERRUN); |
116 | } |
117 | count = tty_insert_flip_string_fixed_flag(port, chars: receive_data->data, |
118 | flag: tty_flags, size: recv_data_size); |
119 | if (count != recv_data_size) { |
120 | dev_err(&gb_tty->gbphy_dev->dev, |
121 | "UART: RX 0x%08x bytes only wrote 0x%08x\n" , |
122 | recv_data_size, count); |
123 | } |
124 | if (count) |
125 | tty_flip_buffer_push(port); |
126 | return 0; |
127 | } |
128 | |
129 | static int gb_uart_serial_state_handler(struct gb_operation *op) |
130 | { |
131 | struct gb_connection *connection = op->connection; |
132 | struct gb_tty *gb_tty = gb_connection_get_data(connection); |
133 | struct gb_message *request = op->request; |
134 | struct gb_uart_serial_state_request *serial_state; |
135 | |
136 | if (request->payload_size < sizeof(*serial_state)) { |
137 | dev_err(&gb_tty->gbphy_dev->dev, |
138 | "short serial-state event received (%zu < %zu)\n" , |
139 | request->payload_size, sizeof(*serial_state)); |
140 | return -EINVAL; |
141 | } |
142 | |
143 | serial_state = request->payload; |
144 | gb_tty->ctrlin = serial_state->control; |
145 | |
146 | return 0; |
147 | } |
148 | |
149 | static int gb_uart_receive_credits_handler(struct gb_operation *op) |
150 | { |
151 | struct gb_connection *connection = op->connection; |
152 | struct gb_tty *gb_tty = gb_connection_get_data(connection); |
153 | struct gb_message *request = op->request; |
154 | struct gb_uart_receive_credits_request *credit_request; |
155 | unsigned long flags; |
156 | unsigned int incoming_credits; |
157 | int ret = 0; |
158 | |
159 | if (request->payload_size < sizeof(*credit_request)) { |
160 | dev_err(&gb_tty->gbphy_dev->dev, |
161 | "short receive_credits event received (%zu < %zu)\n" , |
162 | request->payload_size, |
163 | sizeof(*credit_request)); |
164 | return -EINVAL; |
165 | } |
166 | |
167 | credit_request = request->payload; |
168 | incoming_credits = le16_to_cpu(credit_request->count); |
169 | |
170 | spin_lock_irqsave(&gb_tty->write_lock, flags); |
171 | gb_tty->credits += incoming_credits; |
172 | if (gb_tty->credits > GB_UART_FIRMWARE_CREDITS) { |
173 | gb_tty->credits -= incoming_credits; |
174 | ret = -EINVAL; |
175 | } |
176 | spin_unlock_irqrestore(lock: &gb_tty->write_lock, flags); |
177 | |
178 | if (ret) { |
179 | dev_err(&gb_tty->gbphy_dev->dev, |
180 | "invalid number of incoming credits: %d\n" , |
181 | incoming_credits); |
182 | return ret; |
183 | } |
184 | |
185 | if (!gb_tty->close_pending) |
186 | schedule_work(work: &gb_tty->tx_work); |
187 | |
188 | /* |
189 | * the port the tty layer may be waiting for credits |
190 | */ |
191 | tty_port_tty_wakeup(port: &gb_tty->port); |
192 | |
193 | if (gb_tty->credits == GB_UART_FIRMWARE_CREDITS) |
194 | complete(&gb_tty->credits_complete); |
195 | |
196 | return ret; |
197 | } |
198 | |
199 | static int gb_uart_request_handler(struct gb_operation *op) |
200 | { |
201 | struct gb_connection *connection = op->connection; |
202 | struct gb_tty *gb_tty = gb_connection_get_data(connection); |
203 | int type = op->type; |
204 | int ret; |
205 | |
206 | switch (type) { |
207 | case GB_UART_TYPE_RECEIVE_DATA: |
208 | ret = gb_uart_receive_data_handler(op); |
209 | break; |
210 | case GB_UART_TYPE_SERIAL_STATE: |
211 | ret = gb_uart_serial_state_handler(op); |
212 | break; |
213 | case GB_UART_TYPE_RECEIVE_CREDITS: |
214 | ret = gb_uart_receive_credits_handler(op); |
215 | break; |
216 | default: |
217 | dev_err(&gb_tty->gbphy_dev->dev, |
218 | "unsupported unsolicited request: 0x%02x\n" , type); |
219 | ret = -EINVAL; |
220 | } |
221 | |
222 | return ret; |
223 | } |
224 | |
225 | static void gb_uart_tx_write_work(struct work_struct *work) |
226 | { |
227 | struct gb_uart_send_data_request *request; |
228 | struct gb_tty *gb_tty; |
229 | unsigned long flags; |
230 | unsigned int send_size; |
231 | int ret; |
232 | |
233 | gb_tty = container_of(work, struct gb_tty, tx_work); |
234 | request = gb_tty->buffer; |
235 | |
236 | while (1) { |
237 | if (gb_tty->close_pending) |
238 | break; |
239 | |
240 | spin_lock_irqsave(&gb_tty->write_lock, flags); |
241 | send_size = gb_tty->buffer_payload_max; |
242 | if (send_size > gb_tty->credits) |
243 | send_size = gb_tty->credits; |
244 | |
245 | send_size = kfifo_out_peek(&gb_tty->write_fifo, |
246 | &request->data[0], |
247 | send_size); |
248 | if (!send_size) { |
249 | spin_unlock_irqrestore(lock: &gb_tty->write_lock, flags); |
250 | break; |
251 | } |
252 | |
253 | gb_tty->credits -= send_size; |
254 | spin_unlock_irqrestore(lock: &gb_tty->write_lock, flags); |
255 | |
256 | request->size = cpu_to_le16(send_size); |
257 | ret = gb_operation_sync(connection: gb_tty->connection, |
258 | GB_UART_TYPE_SEND_DATA, |
259 | request, request_size: sizeof(*request) + send_size, |
260 | NULL, response_size: 0); |
261 | if (ret) { |
262 | dev_err(&gb_tty->gbphy_dev->dev, |
263 | "send data error: %d\n" , ret); |
264 | spin_lock_irqsave(&gb_tty->write_lock, flags); |
265 | gb_tty->credits += send_size; |
266 | spin_unlock_irqrestore(lock: &gb_tty->write_lock, flags); |
267 | if (!gb_tty->close_pending) |
268 | schedule_work(work); |
269 | return; |
270 | } |
271 | |
272 | spin_lock_irqsave(&gb_tty->write_lock, flags); |
273 | ret = kfifo_out(&gb_tty->write_fifo, &request->data[0], |
274 | send_size); |
275 | spin_unlock_irqrestore(lock: &gb_tty->write_lock, flags); |
276 | |
277 | tty_port_tty_wakeup(port: &gb_tty->port); |
278 | } |
279 | } |
280 | |
281 | static int send_line_coding(struct gb_tty *tty) |
282 | { |
283 | return gb_operation_sync(connection: tty->connection, GB_UART_TYPE_SET_LINE_CODING, |
284 | request: &tty->line_coding, request_size: sizeof(tty->line_coding), |
285 | NULL, response_size: 0); |
286 | } |
287 | |
288 | static int send_control(struct gb_tty *gb_tty, u8 control) |
289 | { |
290 | struct gb_uart_set_control_line_state_request request; |
291 | |
292 | request.control = control; |
293 | return gb_operation_sync(connection: gb_tty->connection, |
294 | GB_UART_TYPE_SET_CONTROL_LINE_STATE, |
295 | request: &request, request_size: sizeof(request), NULL, response_size: 0); |
296 | } |
297 | |
298 | static int send_break(struct gb_tty *gb_tty, u8 state) |
299 | { |
300 | struct gb_uart_set_break_request request; |
301 | |
302 | if ((state != 0) && (state != 1)) { |
303 | dev_err(&gb_tty->gbphy_dev->dev, |
304 | "invalid break state of %d\n" , state); |
305 | return -EINVAL; |
306 | } |
307 | |
308 | request.state = state; |
309 | return gb_operation_sync(connection: gb_tty->connection, GB_UART_TYPE_SEND_BREAK, |
310 | request: &request, request_size: sizeof(request), NULL, response_size: 0); |
311 | } |
312 | |
313 | static int gb_uart_wait_for_all_credits(struct gb_tty *gb_tty) |
314 | { |
315 | int ret; |
316 | |
317 | if (gb_tty->credits == GB_UART_FIRMWARE_CREDITS) |
318 | return 0; |
319 | |
320 | ret = wait_for_completion_timeout(x: &gb_tty->credits_complete, |
321 | timeout: msecs_to_jiffies(GB_UART_CREDIT_WAIT_TIMEOUT_MSEC)); |
322 | if (!ret) { |
323 | dev_err(&gb_tty->gbphy_dev->dev, |
324 | "time out waiting for credits\n" ); |
325 | return -ETIMEDOUT; |
326 | } |
327 | |
328 | return 0; |
329 | } |
330 | |
331 | static int gb_uart_flush(struct gb_tty *gb_tty, u8 flags) |
332 | { |
333 | struct gb_uart_serial_flush_request request; |
334 | |
335 | request.flags = flags; |
336 | return gb_operation_sync(connection: gb_tty->connection, GB_UART_TYPE_FLUSH_FIFOS, |
337 | request: &request, request_size: sizeof(request), NULL, response_size: 0); |
338 | } |
339 | |
340 | static struct gb_tty *get_gb_by_minor(unsigned int minor) |
341 | { |
342 | struct gb_tty *gb_tty; |
343 | |
344 | mutex_lock(&table_lock); |
345 | gb_tty = idr_find(&tty_minors, id: minor); |
346 | if (gb_tty) { |
347 | mutex_lock(&gb_tty->mutex); |
348 | if (gb_tty->disconnected) { |
349 | mutex_unlock(lock: &gb_tty->mutex); |
350 | gb_tty = NULL; |
351 | } else { |
352 | tty_port_get(port: &gb_tty->port); |
353 | mutex_unlock(lock: &gb_tty->mutex); |
354 | } |
355 | } |
356 | mutex_unlock(lock: &table_lock); |
357 | return gb_tty; |
358 | } |
359 | |
360 | static int alloc_minor(struct gb_tty *gb_tty) |
361 | { |
362 | int minor; |
363 | |
364 | mutex_lock(&table_lock); |
365 | minor = idr_alloc(&tty_minors, ptr: gb_tty, start: 0, GB_NUM_MINORS, GFP_KERNEL); |
366 | mutex_unlock(lock: &table_lock); |
367 | if (minor >= 0) |
368 | gb_tty->minor = minor; |
369 | return minor; |
370 | } |
371 | |
372 | static void release_minor(struct gb_tty *gb_tty) |
373 | { |
374 | int minor = gb_tty->minor; |
375 | |
376 | gb_tty->minor = 0; /* Maybe should use an invalid value instead */ |
377 | mutex_lock(&table_lock); |
378 | idr_remove(&tty_minors, id: minor); |
379 | mutex_unlock(lock: &table_lock); |
380 | } |
381 | |
382 | static int gb_tty_install(struct tty_driver *driver, struct tty_struct *tty) |
383 | { |
384 | struct gb_tty *gb_tty; |
385 | int retval; |
386 | |
387 | gb_tty = get_gb_by_minor(minor: tty->index); |
388 | if (!gb_tty) |
389 | return -ENODEV; |
390 | |
391 | retval = tty_standard_install(driver, tty); |
392 | if (retval) |
393 | goto error; |
394 | |
395 | tty->driver_data = gb_tty; |
396 | return 0; |
397 | error: |
398 | tty_port_put(port: &gb_tty->port); |
399 | return retval; |
400 | } |
401 | |
402 | static int gb_tty_open(struct tty_struct *tty, struct file *file) |
403 | { |
404 | struct gb_tty *gb_tty = tty->driver_data; |
405 | |
406 | return tty_port_open(port: &gb_tty->port, tty, filp: file); |
407 | } |
408 | |
409 | static void gb_tty_close(struct tty_struct *tty, struct file *file) |
410 | { |
411 | struct gb_tty *gb_tty = tty->driver_data; |
412 | |
413 | tty_port_close(port: &gb_tty->port, tty, filp: file); |
414 | } |
415 | |
416 | static void gb_tty_cleanup(struct tty_struct *tty) |
417 | { |
418 | struct gb_tty *gb_tty = tty->driver_data; |
419 | |
420 | tty_port_put(port: &gb_tty->port); |
421 | } |
422 | |
423 | static void gb_tty_hangup(struct tty_struct *tty) |
424 | { |
425 | struct gb_tty *gb_tty = tty->driver_data; |
426 | |
427 | tty_port_hangup(port: &gb_tty->port); |
428 | } |
429 | |
430 | static ssize_t gb_tty_write(struct tty_struct *tty, const u8 *buf, size_t count) |
431 | { |
432 | struct gb_tty *gb_tty = tty->driver_data; |
433 | |
434 | count = kfifo_in_spinlocked(&gb_tty->write_fifo, buf, count, |
435 | &gb_tty->write_lock); |
436 | if (count && !gb_tty->close_pending) |
437 | schedule_work(work: &gb_tty->tx_work); |
438 | |
439 | return count; |
440 | } |
441 | |
442 | static unsigned int gb_tty_write_room(struct tty_struct *tty) |
443 | { |
444 | struct gb_tty *gb_tty = tty->driver_data; |
445 | unsigned long flags; |
446 | int room; |
447 | |
448 | spin_lock_irqsave(&gb_tty->write_lock, flags); |
449 | room = kfifo_avail(&gb_tty->write_fifo); |
450 | spin_unlock_irqrestore(lock: &gb_tty->write_lock, flags); |
451 | |
452 | room -= GB_UART_WRITE_ROOM_MARGIN; |
453 | if (room < 0) |
454 | return 0; |
455 | |
456 | return room; |
457 | } |
458 | |
459 | static unsigned int gb_tty_chars_in_buffer(struct tty_struct *tty) |
460 | { |
461 | struct gb_tty *gb_tty = tty->driver_data; |
462 | unsigned long flags; |
463 | unsigned int chars; |
464 | |
465 | spin_lock_irqsave(&gb_tty->write_lock, flags); |
466 | chars = kfifo_len(&gb_tty->write_fifo); |
467 | if (gb_tty->credits < GB_UART_FIRMWARE_CREDITS) |
468 | chars += GB_UART_FIRMWARE_CREDITS - gb_tty->credits; |
469 | spin_unlock_irqrestore(lock: &gb_tty->write_lock, flags); |
470 | |
471 | return chars; |
472 | } |
473 | |
474 | static int gb_tty_break_ctl(struct tty_struct *tty, int state) |
475 | { |
476 | struct gb_tty *gb_tty = tty->driver_data; |
477 | |
478 | return send_break(gb_tty, state: state ? 1 : 0); |
479 | } |
480 | |
481 | static void gb_tty_set_termios(struct tty_struct *tty, |
482 | const struct ktermios *termios_old) |
483 | { |
484 | struct gb_uart_set_line_coding_request newline; |
485 | struct gb_tty *gb_tty = tty->driver_data; |
486 | struct ktermios *termios = &tty->termios; |
487 | u8 newctrl = gb_tty->ctrlout; |
488 | |
489 | newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); |
490 | newline.format = termios->c_cflag & CSTOPB ? |
491 | GB_SERIAL_2_STOP_BITS : GB_SERIAL_1_STOP_BITS; |
492 | newline.parity = termios->c_cflag & PARENB ? |
493 | (termios->c_cflag & PARODD ? 1 : 2) + |
494 | (termios->c_cflag & CMSPAR ? 2 : 0) : 0; |
495 | |
496 | newline.data_bits = tty_get_char_size(cflag: termios->c_cflag); |
497 | |
498 | /* FIXME: needs to clear unsupported bits in the termios */ |
499 | gb_tty->clocal = ((termios->c_cflag & CLOCAL) != 0); |
500 | |
501 | if (C_BAUD(tty) == B0) { |
502 | newline.rate = gb_tty->line_coding.rate; |
503 | newctrl &= ~(GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); |
504 | } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { |
505 | newctrl |= (GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); |
506 | } |
507 | |
508 | if (newctrl != gb_tty->ctrlout) { |
509 | gb_tty->ctrlout = newctrl; |
510 | send_control(gb_tty, control: newctrl); |
511 | } |
512 | |
513 | if (C_CRTSCTS(tty) && C_BAUD(tty) != B0) |
514 | newline.flow_control = GB_SERIAL_AUTO_RTSCTS_EN; |
515 | else |
516 | newline.flow_control = 0; |
517 | |
518 | if (memcmp(p: &gb_tty->line_coding, q: &newline, size: sizeof(newline))) { |
519 | memcpy(&gb_tty->line_coding, &newline, sizeof(newline)); |
520 | send_line_coding(tty: gb_tty); |
521 | } |
522 | } |
523 | |
524 | static int gb_tty_tiocmget(struct tty_struct *tty) |
525 | { |
526 | struct gb_tty *gb_tty = tty->driver_data; |
527 | |
528 | return (gb_tty->ctrlout & GB_UART_CTRL_DTR ? TIOCM_DTR : 0) | |
529 | (gb_tty->ctrlout & GB_UART_CTRL_RTS ? TIOCM_RTS : 0) | |
530 | (gb_tty->ctrlin & GB_UART_CTRL_DSR ? TIOCM_DSR : 0) | |
531 | (gb_tty->ctrlin & GB_UART_CTRL_RI ? TIOCM_RI : 0) | |
532 | (gb_tty->ctrlin & GB_UART_CTRL_DCD ? TIOCM_CD : 0) | |
533 | TIOCM_CTS; |
534 | } |
535 | |
536 | static int gb_tty_tiocmset(struct tty_struct *tty, unsigned int set, |
537 | unsigned int clear) |
538 | { |
539 | struct gb_tty *gb_tty = tty->driver_data; |
540 | u8 newctrl = gb_tty->ctrlout; |
541 | |
542 | set = (set & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | |
543 | (set & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); |
544 | clear = (clear & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | |
545 | (clear & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); |
546 | |
547 | newctrl = (newctrl & ~clear) | set; |
548 | if (gb_tty->ctrlout == newctrl) |
549 | return 0; |
550 | |
551 | gb_tty->ctrlout = newctrl; |
552 | return send_control(gb_tty, control: newctrl); |
553 | } |
554 | |
555 | static void gb_tty_throttle(struct tty_struct *tty) |
556 | { |
557 | struct gb_tty *gb_tty = tty->driver_data; |
558 | unsigned char stop_char; |
559 | int retval; |
560 | |
561 | if (I_IXOFF(tty)) { |
562 | stop_char = STOP_CHAR(tty); |
563 | retval = gb_tty_write(tty, buf: &stop_char, count: 1); |
564 | if (retval <= 0) |
565 | return; |
566 | } |
567 | |
568 | if (tty->termios.c_cflag & CRTSCTS) { |
569 | gb_tty->ctrlout &= ~GB_UART_CTRL_RTS; |
570 | retval = send_control(gb_tty, control: gb_tty->ctrlout); |
571 | } |
572 | } |
573 | |
574 | static void gb_tty_unthrottle(struct tty_struct *tty) |
575 | { |
576 | struct gb_tty *gb_tty = tty->driver_data; |
577 | unsigned char start_char; |
578 | int retval; |
579 | |
580 | if (I_IXOFF(tty)) { |
581 | start_char = START_CHAR(tty); |
582 | retval = gb_tty_write(tty, buf: &start_char, count: 1); |
583 | if (retval <= 0) |
584 | return; |
585 | } |
586 | |
587 | if (tty->termios.c_cflag & CRTSCTS) { |
588 | gb_tty->ctrlout |= GB_UART_CTRL_RTS; |
589 | retval = send_control(gb_tty, control: gb_tty->ctrlout); |
590 | } |
591 | } |
592 | |
593 | static int get_serial_info(struct tty_struct *tty, |
594 | struct serial_struct *ss) |
595 | { |
596 | struct gb_tty *gb_tty = tty->driver_data; |
597 | |
598 | ss->line = gb_tty->minor; |
599 | ss->close_delay = jiffies_to_msecs(j: gb_tty->port.close_delay) / 10; |
600 | ss->closing_wait = |
601 | gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
602 | ASYNC_CLOSING_WAIT_NONE : |
603 | jiffies_to_msecs(j: gb_tty->port.closing_wait) / 10; |
604 | |
605 | return 0; |
606 | } |
607 | |
608 | static int set_serial_info(struct tty_struct *tty, |
609 | struct serial_struct *ss) |
610 | { |
611 | struct gb_tty *gb_tty = tty->driver_data; |
612 | unsigned int closing_wait; |
613 | unsigned int close_delay; |
614 | int retval = 0; |
615 | |
616 | close_delay = msecs_to_jiffies(m: ss->close_delay * 10); |
617 | closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
618 | ASYNC_CLOSING_WAIT_NONE : |
619 | msecs_to_jiffies(m: ss->closing_wait * 10); |
620 | |
621 | mutex_lock(&gb_tty->port.mutex); |
622 | if (!capable(CAP_SYS_ADMIN)) { |
623 | if ((close_delay != gb_tty->port.close_delay) || |
624 | (closing_wait != gb_tty->port.closing_wait)) |
625 | retval = -EPERM; |
626 | } else { |
627 | gb_tty->port.close_delay = close_delay; |
628 | gb_tty->port.closing_wait = closing_wait; |
629 | } |
630 | mutex_unlock(lock: &gb_tty->port.mutex); |
631 | return retval; |
632 | } |
633 | |
634 | static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) |
635 | { |
636 | int retval = 0; |
637 | DECLARE_WAITQUEUE(wait, current); |
638 | struct async_icount old; |
639 | struct async_icount new; |
640 | |
641 | if (!(arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD))) |
642 | return -EINVAL; |
643 | |
644 | do { |
645 | spin_lock_irq(lock: &gb_tty->read_lock); |
646 | old = gb_tty->oldcount; |
647 | new = gb_tty->iocount; |
648 | gb_tty->oldcount = new; |
649 | spin_unlock_irq(lock: &gb_tty->read_lock); |
650 | |
651 | if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) |
652 | break; |
653 | if ((arg & TIOCM_CD) && (old.dcd != new.dcd)) |
654 | break; |
655 | if ((arg & TIOCM_RI) && (old.rng != new.rng)) |
656 | break; |
657 | |
658 | add_wait_queue(wq_head: &gb_tty->wioctl, wq_entry: &wait); |
659 | set_current_state(TASK_INTERRUPTIBLE); |
660 | schedule(); |
661 | remove_wait_queue(wq_head: &gb_tty->wioctl, wq_entry: &wait); |
662 | if (gb_tty->disconnected) { |
663 | if (arg & TIOCM_CD) |
664 | break; |
665 | retval = -ENODEV; |
666 | } else if (signal_pending(current)) { |
667 | retval = -ERESTARTSYS; |
668 | } |
669 | } while (!retval); |
670 | |
671 | return retval; |
672 | } |
673 | |
674 | static int gb_tty_get_icount(struct tty_struct *tty, |
675 | struct serial_icounter_struct *icount) |
676 | { |
677 | struct gb_tty *gb_tty = tty->driver_data; |
678 | |
679 | icount->dsr = gb_tty->iocount.dsr; |
680 | icount->rng = gb_tty->iocount.rng; |
681 | icount->dcd = gb_tty->iocount.dcd; |
682 | icount->frame = gb_tty->iocount.frame; |
683 | icount->overrun = gb_tty->iocount.overrun; |
684 | icount->parity = gb_tty->iocount.parity; |
685 | icount->brk = gb_tty->iocount.brk; |
686 | |
687 | return 0; |
688 | } |
689 | |
690 | static int gb_tty_ioctl(struct tty_struct *tty, unsigned int cmd, |
691 | unsigned long arg) |
692 | { |
693 | struct gb_tty *gb_tty = tty->driver_data; |
694 | |
695 | switch (cmd) { |
696 | case TIOCMIWAIT: |
697 | return wait_serial_change(gb_tty, arg); |
698 | } |
699 | |
700 | return -ENOIOCTLCMD; |
701 | } |
702 | |
703 | static void gb_tty_dtr_rts(struct tty_port *port, bool active) |
704 | { |
705 | struct gb_tty *gb_tty; |
706 | u8 newctrl; |
707 | |
708 | gb_tty = container_of(port, struct gb_tty, port); |
709 | newctrl = gb_tty->ctrlout; |
710 | |
711 | if (active) |
712 | newctrl |= (GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); |
713 | else |
714 | newctrl &= ~(GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); |
715 | |
716 | gb_tty->ctrlout = newctrl; |
717 | send_control(gb_tty, control: newctrl); |
718 | } |
719 | |
720 | static int gb_tty_port_activate(struct tty_port *port, |
721 | struct tty_struct *tty) |
722 | { |
723 | struct gb_tty *gb_tty; |
724 | |
725 | gb_tty = container_of(port, struct gb_tty, port); |
726 | |
727 | return gbphy_runtime_get_sync(gbphy_dev: gb_tty->gbphy_dev); |
728 | } |
729 | |
730 | static void gb_tty_port_shutdown(struct tty_port *port) |
731 | { |
732 | struct gb_tty *gb_tty; |
733 | unsigned long flags; |
734 | int ret; |
735 | |
736 | gb_tty = container_of(port, struct gb_tty, port); |
737 | |
738 | gb_tty->close_pending = true; |
739 | |
740 | cancel_work_sync(work: &gb_tty->tx_work); |
741 | |
742 | spin_lock_irqsave(&gb_tty->write_lock, flags); |
743 | kfifo_reset_out(&gb_tty->write_fifo); |
744 | spin_unlock_irqrestore(lock: &gb_tty->write_lock, flags); |
745 | |
746 | if (gb_tty->credits == GB_UART_FIRMWARE_CREDITS) |
747 | goto out; |
748 | |
749 | ret = gb_uart_flush(gb_tty, GB_SERIAL_FLAG_FLUSH_TRANSMITTER); |
750 | if (ret) { |
751 | dev_err(&gb_tty->gbphy_dev->dev, |
752 | "error flushing transmitter: %d\n" , ret); |
753 | } |
754 | |
755 | gb_uart_wait_for_all_credits(gb_tty); |
756 | |
757 | out: |
758 | gb_tty->close_pending = false; |
759 | |
760 | gbphy_runtime_put_autosuspend(gbphy_dev: gb_tty->gbphy_dev); |
761 | } |
762 | |
763 | static void gb_tty_port_destruct(struct tty_port *port) |
764 | { |
765 | struct gb_tty *gb_tty = container_of(port, struct gb_tty, port); |
766 | |
767 | if (gb_tty->minor != GB_NUM_MINORS) |
768 | release_minor(gb_tty); |
769 | kfifo_free(&gb_tty->write_fifo); |
770 | kfree(objp: gb_tty->buffer); |
771 | kfree(objp: gb_tty); |
772 | } |
773 | |
774 | static const struct tty_operations gb_ops = { |
775 | .install = gb_tty_install, |
776 | .open = gb_tty_open, |
777 | .close = gb_tty_close, |
778 | .cleanup = gb_tty_cleanup, |
779 | .hangup = gb_tty_hangup, |
780 | .write = gb_tty_write, |
781 | .write_room = gb_tty_write_room, |
782 | .ioctl = gb_tty_ioctl, |
783 | .throttle = gb_tty_throttle, |
784 | .unthrottle = gb_tty_unthrottle, |
785 | .chars_in_buffer = gb_tty_chars_in_buffer, |
786 | .break_ctl = gb_tty_break_ctl, |
787 | .set_termios = gb_tty_set_termios, |
788 | .tiocmget = gb_tty_tiocmget, |
789 | .tiocmset = gb_tty_tiocmset, |
790 | .get_icount = gb_tty_get_icount, |
791 | .set_serial = set_serial_info, |
792 | .get_serial = get_serial_info, |
793 | }; |
794 | |
795 | static const struct tty_port_operations gb_port_ops = { |
796 | .dtr_rts = gb_tty_dtr_rts, |
797 | .activate = gb_tty_port_activate, |
798 | .shutdown = gb_tty_port_shutdown, |
799 | .destruct = gb_tty_port_destruct, |
800 | }; |
801 | |
802 | static int gb_uart_probe(struct gbphy_device *gbphy_dev, |
803 | const struct gbphy_device_id *id) |
804 | { |
805 | struct gb_connection *connection; |
806 | size_t max_payload; |
807 | struct gb_tty *gb_tty; |
808 | struct device *tty_dev; |
809 | int retval; |
810 | int minor; |
811 | |
812 | connection = gb_connection_create(bundle: gbphy_dev->bundle, |
813 | le16_to_cpu(gbphy_dev->cport_desc->id), |
814 | handler: gb_uart_request_handler); |
815 | if (IS_ERR(ptr: connection)) |
816 | return PTR_ERR(ptr: connection); |
817 | |
818 | max_payload = gb_operation_get_payload_size_max(connection); |
819 | if (max_payload < sizeof(struct gb_uart_send_data_request)) { |
820 | retval = -EINVAL; |
821 | goto exit_connection_destroy; |
822 | } |
823 | |
824 | gb_tty = kzalloc(size: sizeof(*gb_tty), GFP_KERNEL); |
825 | if (!gb_tty) { |
826 | retval = -ENOMEM; |
827 | goto exit_connection_destroy; |
828 | } |
829 | |
830 | tty_port_init(port: &gb_tty->port); |
831 | gb_tty->port.ops = &gb_port_ops; |
832 | gb_tty->minor = GB_NUM_MINORS; |
833 | |
834 | gb_tty->buffer_payload_max = max_payload - |
835 | sizeof(struct gb_uart_send_data_request); |
836 | |
837 | gb_tty->buffer = kzalloc(size: gb_tty->buffer_payload_max, GFP_KERNEL); |
838 | if (!gb_tty->buffer) { |
839 | retval = -ENOMEM; |
840 | goto exit_put_port; |
841 | } |
842 | |
843 | INIT_WORK(&gb_tty->tx_work, gb_uart_tx_write_work); |
844 | |
845 | retval = kfifo_alloc(&gb_tty->write_fifo, GB_UART_WRITE_FIFO_SIZE, |
846 | GFP_KERNEL); |
847 | if (retval) |
848 | goto exit_put_port; |
849 | |
850 | gb_tty->credits = GB_UART_FIRMWARE_CREDITS; |
851 | init_completion(x: &gb_tty->credits_complete); |
852 | |
853 | minor = alloc_minor(gb_tty); |
854 | if (minor < 0) { |
855 | if (minor == -ENOSPC) { |
856 | dev_err(&gbphy_dev->dev, |
857 | "no more free minor numbers\n" ); |
858 | retval = -ENODEV; |
859 | } else { |
860 | retval = minor; |
861 | } |
862 | goto exit_put_port; |
863 | } |
864 | |
865 | gb_tty->minor = minor; |
866 | spin_lock_init(&gb_tty->write_lock); |
867 | spin_lock_init(&gb_tty->read_lock); |
868 | init_waitqueue_head(&gb_tty->wioctl); |
869 | mutex_init(&gb_tty->mutex); |
870 | |
871 | gb_tty->connection = connection; |
872 | gb_tty->gbphy_dev = gbphy_dev; |
873 | gb_connection_set_data(connection, data: gb_tty); |
874 | gb_gbphy_set_data(gdev: gbphy_dev, data: gb_tty); |
875 | |
876 | retval = gb_connection_enable_tx(connection); |
877 | if (retval) |
878 | goto exit_put_port; |
879 | |
880 | send_control(gb_tty, control: gb_tty->ctrlout); |
881 | |
882 | /* initialize the uart to be 9600n81 */ |
883 | gb_tty->line_coding.rate = cpu_to_le32(9600); |
884 | gb_tty->line_coding.format = GB_SERIAL_1_STOP_BITS; |
885 | gb_tty->line_coding.parity = GB_SERIAL_NO_PARITY; |
886 | gb_tty->line_coding.data_bits = 8; |
887 | send_line_coding(tty: gb_tty); |
888 | |
889 | retval = gb_connection_enable(connection); |
890 | if (retval) |
891 | goto exit_connection_disable; |
892 | |
893 | tty_dev = tty_port_register_device(port: &gb_tty->port, driver: gb_tty_driver, index: minor, |
894 | device: &gbphy_dev->dev); |
895 | if (IS_ERR(ptr: tty_dev)) { |
896 | retval = PTR_ERR(ptr: tty_dev); |
897 | goto exit_connection_disable; |
898 | } |
899 | |
900 | gbphy_runtime_put_autosuspend(gbphy_dev); |
901 | return 0; |
902 | |
903 | exit_connection_disable: |
904 | gb_connection_disable(connection); |
905 | exit_put_port: |
906 | tty_port_put(port: &gb_tty->port); |
907 | exit_connection_destroy: |
908 | gb_connection_destroy(connection); |
909 | |
910 | return retval; |
911 | } |
912 | |
913 | static void gb_uart_remove(struct gbphy_device *gbphy_dev) |
914 | { |
915 | struct gb_tty *gb_tty = gb_gbphy_get_data(gdev: gbphy_dev); |
916 | struct gb_connection *connection = gb_tty->connection; |
917 | struct tty_struct *tty; |
918 | int ret; |
919 | |
920 | ret = gbphy_runtime_get_sync(gbphy_dev); |
921 | if (ret) |
922 | gbphy_runtime_get_noresume(gbphy_dev); |
923 | |
924 | mutex_lock(&gb_tty->mutex); |
925 | gb_tty->disconnected = true; |
926 | |
927 | wake_up_all(&gb_tty->wioctl); |
928 | mutex_unlock(lock: &gb_tty->mutex); |
929 | |
930 | tty = tty_port_tty_get(port: &gb_tty->port); |
931 | if (tty) { |
932 | tty_vhangup(tty); |
933 | tty_kref_put(tty); |
934 | } |
935 | |
936 | gb_connection_disable_rx(connection); |
937 | tty_unregister_device(driver: gb_tty_driver, index: gb_tty->minor); |
938 | |
939 | gb_connection_disable(connection); |
940 | gb_connection_destroy(connection); |
941 | |
942 | tty_port_put(port: &gb_tty->port); |
943 | } |
944 | |
945 | static int gb_tty_init(void) |
946 | { |
947 | int retval = 0; |
948 | |
949 | gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, 0); |
950 | if (IS_ERR(ptr: gb_tty_driver)) { |
951 | pr_err("Can not allocate tty driver\n" ); |
952 | retval = -ENOMEM; |
953 | goto fail_unregister_dev; |
954 | } |
955 | |
956 | gb_tty_driver->driver_name = "gb" ; |
957 | gb_tty_driver->name = GB_NAME; |
958 | gb_tty_driver->major = 0; |
959 | gb_tty_driver->minor_start = 0; |
960 | gb_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; |
961 | gb_tty_driver->subtype = SERIAL_TYPE_NORMAL; |
962 | gb_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
963 | gb_tty_driver->init_termios = tty_std_termios; |
964 | gb_tty_driver->init_termios.c_cflag = B9600 | CS8 | |
965 | CREAD | HUPCL | CLOCAL; |
966 | tty_set_operations(driver: gb_tty_driver, op: &gb_ops); |
967 | |
968 | retval = tty_register_driver(driver: gb_tty_driver); |
969 | if (retval) { |
970 | pr_err("Can not register tty driver: %d\n" , retval); |
971 | goto fail_put_gb_tty; |
972 | } |
973 | |
974 | return 0; |
975 | |
976 | fail_put_gb_tty: |
977 | tty_driver_kref_put(driver: gb_tty_driver); |
978 | fail_unregister_dev: |
979 | return retval; |
980 | } |
981 | |
982 | static void gb_tty_exit(void) |
983 | { |
984 | tty_unregister_driver(driver: gb_tty_driver); |
985 | tty_driver_kref_put(driver: gb_tty_driver); |
986 | idr_destroy(&tty_minors); |
987 | } |
988 | |
989 | static const struct gbphy_device_id gb_uart_id_table[] = { |
990 | { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_UART) }, |
991 | { }, |
992 | }; |
993 | MODULE_DEVICE_TABLE(gbphy, gb_uart_id_table); |
994 | |
995 | static struct gbphy_driver uart_driver = { |
996 | .name = "uart" , |
997 | .probe = gb_uart_probe, |
998 | .remove = gb_uart_remove, |
999 | .id_table = gb_uart_id_table, |
1000 | }; |
1001 | |
1002 | static int gb_uart_driver_init(void) |
1003 | { |
1004 | int ret; |
1005 | |
1006 | ret = gb_tty_init(); |
1007 | if (ret) |
1008 | return ret; |
1009 | |
1010 | ret = gb_gbphy_register(&uart_driver); |
1011 | if (ret) { |
1012 | gb_tty_exit(); |
1013 | return ret; |
1014 | } |
1015 | |
1016 | return 0; |
1017 | } |
1018 | module_init(gb_uart_driver_init); |
1019 | |
1020 | static void gb_uart_driver_exit(void) |
1021 | { |
1022 | gb_gbphy_deregister(&uart_driver); |
1023 | gb_tty_exit(); |
1024 | } |
1025 | |
1026 | module_exit(gb_uart_driver_exit); |
1027 | MODULE_LICENSE("GPL v2" ); |
1028 | |