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>
18 #define SERPORT_ACTIVE 1
21 struct tty_port
*port
;
22 struct tty_struct
*tty
;
23 struct tty_driver
*tty_drv
;
29 * Callback functions from the tty port.
32 static int ttyport_receive_buf(struct tty_port
*port
, const unsigned char *cp
,
33 const unsigned char *fp
, size_t count
)
35 struct serdev_controller
*ctrl
= port
->client_data
;
36 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
38 if (!test_bit(SERPORT_ACTIVE
, &serport
->flags
))
41 return serdev_controller_receive_buf(ctrl
, cp
, count
);
44 static void ttyport_write_wakeup(struct tty_port
*port
)
46 struct serdev_controller
*ctrl
= port
->client_data
;
47 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
49 if (!test_and_clear_bit(TTY_DO_WRITE_WAKEUP
, &port
->tty
->flags
))
52 if (test_bit(SERPORT_ACTIVE
, &serport
->flags
))
53 serdev_controller_write_wakeup(ctrl
);
56 static const struct tty_port_client_operations client_ops
= {
57 .receive_buf
= ttyport_receive_buf
,
58 .write_wakeup
= ttyport_write_wakeup
,
62 * Callback functions from the serdev core.
65 static int ttyport_write_buf(struct serdev_controller
*ctrl
, const unsigned char *data
, size_t len
)
67 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
68 struct tty_struct
*tty
= serport
->tty
;
70 if (!test_bit(SERPORT_ACTIVE
, &serport
->flags
))
73 set_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
);
74 return tty
->ops
->write(serport
->tty
, data
, len
);
77 static void ttyport_write_flush(struct serdev_controller
*ctrl
)
79 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
80 struct tty_struct
*tty
= serport
->tty
;
82 tty_driver_flush_buffer(tty
);
85 static int ttyport_write_room(struct serdev_controller
*ctrl
)
87 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
88 struct tty_struct
*tty
= serport
->tty
;
90 return tty_write_room(tty
);
93 static int ttyport_open(struct serdev_controller
*ctrl
)
95 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
96 struct tty_struct
*tty
;
97 struct ktermios ktermios
;
99 tty
= tty_init_dev(serport
->tty_drv
, serport
->tty_idx
);
104 serport
->port
->client_ops
= &client_ops
;
105 serport
->port
->client_data
= ctrl
;
108 tty
->ops
->open(serport
->tty
, NULL
);
110 tty_port_open(serport
->port
, tty
, NULL
);
112 /* Bring the UART into a known 8 bits no parity hw fc state */
113 ktermios
= tty
->termios
;
114 ktermios
.c_iflag
&= ~(IGNBRK
| BRKINT
| PARMRK
| ISTRIP
|
115 INLCR
| IGNCR
| ICRNL
| IXON
);
116 ktermios
.c_oflag
&= ~OPOST
;
117 ktermios
.c_lflag
&= ~(ECHO
| ECHONL
| ICANON
| ISIG
| IEXTEN
);
118 ktermios
.c_cflag
&= ~(CSIZE
| PARENB
);
119 ktermios
.c_cflag
|= CS8
;
120 ktermios
.c_cflag
|= CRTSCTS
;
121 tty_set_termios(tty
, &ktermios
);
123 set_bit(SERPORT_ACTIVE
, &serport
->flags
);
125 tty_unlock(serport
->tty
);
129 static void ttyport_close(struct serdev_controller
*ctrl
)
131 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
132 struct tty_struct
*tty
= serport
->tty
;
134 clear_bit(SERPORT_ACTIVE
, &serport
->flags
);
137 tty
->ops
->close(tty
, NULL
);
139 tty_release_struct(tty
, serport
->tty_idx
);
142 static unsigned int ttyport_set_baudrate(struct serdev_controller
*ctrl
, unsigned int speed
)
144 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
145 struct tty_struct
*tty
= serport
->tty
;
146 struct ktermios ktermios
= tty
->termios
;
148 ktermios
.c_cflag
&= ~CBAUD
;
149 tty_termios_encode_baud_rate(&ktermios
, speed
, speed
);
151 /* tty_set_termios() return not checked as it is always 0 */
152 tty_set_termios(tty
, &ktermios
);
156 static void ttyport_set_flow_control(struct serdev_controller
*ctrl
, bool enable
)
158 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
159 struct tty_struct
*tty
= serport
->tty
;
160 struct ktermios ktermios
= tty
->termios
;
163 ktermios
.c_cflag
|= CRTSCTS
;
165 ktermios
.c_cflag
&= ~CRTSCTS
;
167 tty_set_termios(tty
, &ktermios
);
170 static const struct serdev_controller_ops ctrl_ops
= {
171 .write_buf
= ttyport_write_buf
,
172 .write_flush
= ttyport_write_flush
,
173 .write_room
= ttyport_write_room
,
174 .open
= ttyport_open
,
175 .close
= ttyport_close
,
176 .set_flow_control
= ttyport_set_flow_control
,
177 .set_baudrate
= ttyport_set_baudrate
,
180 struct device
*serdev_tty_port_register(struct tty_port
*port
,
181 struct device
*parent
,
182 struct tty_driver
*drv
, int idx
)
184 struct serdev_controller
*ctrl
;
185 struct serport
*serport
;
188 if (!port
|| !drv
|| !parent
)
189 return ERR_PTR(-ENODEV
);
191 ctrl
= serdev_controller_alloc(parent
, sizeof(struct serport
));
193 return ERR_PTR(-ENOMEM
);
194 serport
= serdev_controller_get_drvdata(ctrl
);
196 serport
->port
= port
;
197 serport
->tty_idx
= idx
;
198 serport
->tty_drv
= drv
;
200 ctrl
->ops
= &ctrl_ops
;
202 ret
= serdev_controller_add(ctrl
);
204 goto err_controller_put
;
206 dev_info(&ctrl
->dev
, "tty port %s%d registered\n", drv
->name
, idx
);
210 serdev_controller_put(ctrl
);
214 void serdev_tty_port_unregister(struct tty_port
*port
)
216 struct serdev_controller
*ctrl
= port
->client_data
;
217 struct serport
*serport
= serdev_controller_get_drvdata(ctrl
);
222 serdev_controller_remove(ctrl
);
223 port
->client_ops
= NULL
;
224 port
->client_data
= NULL
;
225 serdev_controller_put(ctrl
);