1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <robh@kernel.org> 4 */ 5 #include <linux/kernel.h> 6 #include <linux/serdev.h> 7 #include <linux/tty.h> 8 #include <linux/tty_driver.h> 9 #include <linux/poll.h> 10 11 #define SERPORT_ACTIVE 1 12 13 struct serport { 14 struct tty_port *port; 15 struct tty_struct *tty; 16 struct tty_driver *tty_drv; 17 int tty_idx; 18 unsigned long flags; 19 }; 20 21 /* 22 * Callback functions from the tty port. 23 */ 24 25 static size_t ttyport_receive_buf(struct tty_port *port, const u8 *cp, 26 const u8 *fp, size_t count) 27 { 28 struct serdev_controller *ctrl = port->client_data; 29 struct serport *serport = serdev_controller_get_drvdata(ctrl); 30 size_t ret; 31 32 if (!test_bit(SERPORT_ACTIVE, &serport->flags)) 33 return 0; 34 35 ret = serdev_controller_receive_buf(ctrl, cp, count); 36 37 dev_WARN_ONCE(&ctrl->dev, ret > count, 38 "receive_buf returns %zu (count = %zu)\n", 39 ret, count); 40 if (ret > count) 41 return count; 42 43 return ret; 44 } 45 46 static void ttyport_write_wakeup(struct tty_port *port) 47 { 48 struct serdev_controller *ctrl = port->client_data; 49 struct serport *serport = serdev_controller_get_drvdata(ctrl); 50 struct tty_struct *tty; 51 52 tty = tty_port_tty_get(port); 53 if (!tty) 54 return; 55 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); 59 60 /* Wake up any tty_wait_until_sent() */ 61 wake_up_interruptible(&tty->write_wait); 62 63 tty_kref_put(tty); 64 } 65 66 static const struct tty_port_client_operations client_ops = { 67 .receive_buf = ttyport_receive_buf, 68 .write_wakeup = ttyport_write_wakeup, 69 }; 70 71 /* 72 * Callback functions from the serdev core. 73 */ 74 75 static ssize_t ttyport_write_buf(struct serdev_controller *ctrl, const u8 *data, size_t len) 76 { 77 struct serport *serport = serdev_controller_get_drvdata(ctrl); 78 struct tty_struct *tty = serport->tty; 79 80 if (!test_bit(SERPORT_ACTIVE, &serport->flags)) 81 return 0; 82 83 set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); 84 return tty->ops->write(serport->tty, data, len); 85 } 86 87 static void ttyport_write_flush(struct serdev_controller *ctrl) 88 { 89 struct serport *serport = serdev_controller_get_drvdata(ctrl); 90 struct tty_struct *tty = serport->tty; 91 92 tty_driver_flush_buffer(tty); 93 } 94 95 static int ttyport_write_room(struct serdev_controller *ctrl) 96 { 97 struct serport *serport = serdev_controller_get_drvdata(ctrl); 98 struct tty_struct *tty = serport->tty; 99 100 return tty_write_room(tty); 101 } 102 103 static int ttyport_open(struct serdev_controller *ctrl) 104 { 105 struct serport *serport = serdev_controller_get_drvdata(ctrl); 106 struct tty_struct *tty; 107 struct ktermios ktermios; 108 int ret; 109 110 tty = tty_init_dev(serport->tty_drv, serport->tty_idx); 111 if (IS_ERR(tty)) 112 return PTR_ERR(tty); 113 serport->tty = tty; 114 115 if (!tty->ops->open || !tty->ops->close) { 116 ret = -ENODEV; 117 goto err_unlock; 118 } 119 120 ret = tty->ops->open(serport->tty, NULL); 121 if (ret) 122 goto err_close; 123 124 tty_unlock(serport->tty); 125 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); 138 139 set_bit(SERPORT_ACTIVE, &serport->flags); 140 141 return 0; 142 143 err_close: 144 tty->ops->close(tty, NULL); 145 err_unlock: 146 tty_unlock(tty); 147 tty_release_struct(tty, serport->tty_idx); 148 149 return ret; 150 } 151 152 static void ttyport_close(struct serdev_controller *ctrl) 153 { 154 struct serport *serport = serdev_controller_get_drvdata(ctrl); 155 struct tty_struct *tty = serport->tty; 156 157 clear_bit(SERPORT_ACTIVE, &serport->flags); 158 159 tty_lock(tty); 160 if (tty->ops->close) 161 tty->ops->close(tty, NULL); 162 tty_unlock(tty); 163 164 tty_release_struct(tty, serport->tty_idx); 165 } 166 167 static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, unsigned int speed) 168 { 169 struct serport *serport = serdev_controller_get_drvdata(ctrl); 170 struct tty_struct *tty = serport->tty; 171 struct ktermios ktermios = tty->termios; 172 173 ktermios.c_cflag &= ~CBAUD; 174 tty_termios_encode_baud_rate(&ktermios, speed, speed); 175 176 /* tty_set_termios() return not checked as it is always 0 */ 177 tty_set_termios(tty, &ktermios); 178 return ktermios.c_ospeed; 179 } 180 181 static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable) 182 { 183 struct serport *serport = serdev_controller_get_drvdata(ctrl); 184 struct tty_struct *tty = serport->tty; 185 struct ktermios ktermios = tty->termios; 186 187 if (enable) 188 ktermios.c_cflag |= CRTSCTS; 189 else 190 ktermios.c_cflag &= ~CRTSCTS; 191 192 tty_set_termios(tty, &ktermios); 193 } 194 195 static int ttyport_set_parity(struct serdev_controller *ctrl, 196 enum serdev_parity parity) 197 { 198 struct serport *serport = serdev_controller_get_drvdata(ctrl); 199 struct tty_struct *tty = serport->tty; 200 struct ktermios ktermios = tty->termios; 201 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; 207 } 208 209 tty_set_termios(tty, &ktermios); 210 211 if ((tty->termios.c_cflag & (PARENB | PARODD | CMSPAR)) != 212 (ktermios.c_cflag & (PARENB | PARODD | CMSPAR))) 213 return -EINVAL; 214 215 return 0; 216 } 217 218 static void ttyport_wait_until_sent(struct serdev_controller *ctrl, long timeout) 219 { 220 struct serport *serport = serdev_controller_get_drvdata(ctrl); 221 struct tty_struct *tty = serport->tty; 222 223 tty_wait_until_sent(tty, timeout); 224 } 225 226 static int ttyport_get_tiocm(struct serdev_controller *ctrl) 227 { 228 struct serport *serport = serdev_controller_get_drvdata(ctrl); 229 struct tty_struct *tty = serport->tty; 230 231 if (!tty->ops->tiocmget) 232 return -EOPNOTSUPP; 233 234 return tty->ops->tiocmget(tty); 235 } 236 237 static int ttyport_set_tiocm(struct serdev_controller *ctrl, unsigned int set, unsigned int clear) 238 { 239 struct serport *serport = serdev_controller_get_drvdata(ctrl); 240 struct tty_struct *tty = serport->tty; 241 242 if (!tty->ops->tiocmset) 243 return -EOPNOTSUPP; 244 245 return tty->ops->tiocmset(tty, set, clear); 246 } 247 248 static int ttyport_break_ctl(struct serdev_controller *ctrl, unsigned int break_state) 249 { 250 struct serport *serport = serdev_controller_get_drvdata(ctrl); 251 struct tty_struct *tty = serport->tty; 252 253 if (!tty->ops->break_ctl) 254 return -EOPNOTSUPP; 255 256 return tty->ops->break_ctl(tty, break_state); 257 } 258 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, 272 }; 273 274 struct device *serdev_tty_port_register(struct tty_port *port, 275 struct device *host, 276 struct device *parent, 277 struct tty_driver *drv, int idx) 278 { 279 struct serdev_controller *ctrl; 280 struct serport *serport; 281 int ret; 282 283 if (!port || !drv || !parent) 284 return ERR_PTR(-ENODEV); 285 286 ctrl = serdev_controller_alloc(host, parent, sizeof(struct serport)); 287 if (!ctrl) 288 return ERR_PTR(-ENOMEM); 289 serport = serdev_controller_get_drvdata(ctrl); 290 291 serport->port = port; 292 serport->tty_idx = idx; 293 serport->tty_drv = drv; 294 295 ctrl->ops = &ctrl_ops; 296 297 port->client_ops = &client_ops; 298 port->client_data = ctrl; 299 300 ret = serdev_controller_add(ctrl); 301 if (ret) 302 goto err_reset_data; 303 304 dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx); 305 return &ctrl->dev; 306 307 err_reset_data: 308 port->client_data = NULL; 309 port->client_ops = &tty_port_default_client_ops; 310 serdev_controller_put(ctrl); 311 312 return ERR_PTR(ret); 313 } 314 315 int serdev_tty_port_unregister(struct tty_port *port) 316 { 317 struct serdev_controller *ctrl = port->client_data; 318 struct serport *serport = serdev_controller_get_drvdata(ctrl); 319 320 if (!serport) 321 return -ENODEV; 322 323 serdev_controller_remove(ctrl); 324 port->client_data = NULL; 325 port->client_ops = &tty_port_default_client_ops; 326 serdev_controller_put(ctrl); 327 328 return 0; 329 } 330