1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Renesas Electronics uPD78F0730 USB to serial converter driver 4 * 5 * Copyright (C) 2014,2016 Maksim Salau <maksim.salau@gmail.com> 6 * 7 * Protocol of the adaptor is described in the application note U19660EJ1V0AN00 8 * μPD78F0730 8-bit Single-Chip Microcontroller 9 * USB-to-Serial Conversion Software 10 * <https://www.renesas.com/en-eu/doc/DocumentServer/026/U19660EJ1V0AN00.pdf> 11 * 12 * The adaptor functionality is limited to the following: 13 * - data bits: 7 or 8 14 * - stop bits: 1 or 2 15 * - parity: even, odd or none 16 * - flow control: none 17 * - baud rates: 0, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 153600 18 * - signals: DTR, RTS and BREAK 19 */ 20 21 #include <linux/module.h> 22 #include <linux/slab.h> 23 #include <linux/tty.h> 24 #include <linux/usb.h> 25 #include <linux/usb/serial.h> 26 27 #define DRIVER_DESC "Renesas uPD78F0730 USB to serial converter driver" 28 29 #define DRIVER_AUTHOR "Maksim Salau <maksim.salau@gmail.com>" 30 31 static const struct usb_device_id id_table[] = { 32 { USB_DEVICE(0x0409, 0x0063) }, /* V850ESJX3-STICK */ 33 { USB_DEVICE(0x045B, 0x0212) }, /* YRPBRL78G13, YRPBRL78G14 */ 34 { USB_DEVICE(0x064B, 0x7825) }, /* Analog Devices EVAL-ADXL362Z-DB */ 35 {} 36 }; 37 38 MODULE_DEVICE_TABLE(usb, id_table); 39 40 /* 41 * Each adaptor is associated with a private structure, that holds the current 42 * state of control signals (DTR, RTS and BREAK). 43 */ 44 struct upd78f0730_port_private { 45 struct mutex lock; /* mutex to protect line_signals */ 46 u8 line_signals; 47 }; 48 49 /* Op-codes of control commands */ 50 #define UPD78F0730_CMD_LINE_CONTROL 0x00 51 #define UPD78F0730_CMD_SET_DTR_RTS 0x01 52 #define UPD78F0730_CMD_SET_XON_XOFF_CHR 0x02 53 #define UPD78F0730_CMD_OPEN_CLOSE 0x03 54 #define UPD78F0730_CMD_SET_ERR_CHR 0x04 55 56 /* Data sizes in UPD78F0730_CMD_LINE_CONTROL command */ 57 #define UPD78F0730_DATA_SIZE_7_BITS 0x00 58 #define UPD78F0730_DATA_SIZE_8_BITS 0x01 59 #define UPD78F0730_DATA_SIZE_MASK 0x01 60 61 /* Stop-bit modes in UPD78F0730_CMD_LINE_CONTROL command */ 62 #define UPD78F0730_STOP_BIT_1_BIT 0x00 63 #define UPD78F0730_STOP_BIT_2_BIT 0x02 64 #define UPD78F0730_STOP_BIT_MASK 0x02 65 66 /* Parity modes in UPD78F0730_CMD_LINE_CONTROL command */ 67 #define UPD78F0730_PARITY_NONE 0x00 68 #define UPD78F0730_PARITY_EVEN 0x04 69 #define UPD78F0730_PARITY_ODD 0x08 70 #define UPD78F0730_PARITY_MASK 0x0C 71 72 /* Flow control modes in UPD78F0730_CMD_LINE_CONTROL command */ 73 #define UPD78F0730_FLOW_CONTROL_NONE 0x00 74 #define UPD78F0730_FLOW_CONTROL_HW 0x10 75 #define UPD78F0730_FLOW_CONTROL_SW 0x20 76 #define UPD78F0730_FLOW_CONTROL_MASK 0x30 77 78 /* Control signal bits in UPD78F0730_CMD_SET_DTR_RTS command */ 79 #define UPD78F0730_RTS 0x01 80 #define UPD78F0730_DTR 0x02 81 #define UPD78F0730_BREAK 0x04 82 83 /* Port modes in UPD78F0730_CMD_OPEN_CLOSE command */ 84 #define UPD78F0730_PORT_CLOSE 0x00 85 #define UPD78F0730_PORT_OPEN 0x01 86 87 /* Error character substitution modes in UPD78F0730_CMD_SET_ERR_CHR command */ 88 #define UPD78F0730_ERR_CHR_DISABLED 0x00 89 #define UPD78F0730_ERR_CHR_ENABLED 0x01 90 91 /* 92 * Declaration of command structures 93 */ 94 95 /* UPD78F0730_CMD_LINE_CONTROL command */ 96 struct upd78f0730_line_control { 97 u8 opcode; 98 __le32 baud_rate; 99 u8 params; 100 } __packed; 101 102 /* UPD78F0730_CMD_SET_DTR_RTS command */ 103 struct upd78f0730_set_dtr_rts { 104 u8 opcode; 105 u8 params; 106 }; 107 108 /* UPD78F0730_CMD_SET_XON_OFF_CHR command */ 109 struct upd78f0730_set_xon_xoff_chr { 110 u8 opcode; 111 u8 xon; 112 u8 xoff; 113 }; 114 115 /* UPD78F0730_CMD_OPEN_CLOSE command */ 116 struct upd78f0730_open_close { 117 u8 opcode; 118 u8 state; 119 }; 120 121 /* UPD78F0730_CMD_SET_ERR_CHR command */ 122 struct upd78f0730_set_err_chr { 123 u8 opcode; 124 u8 state; 125 u8 err_char; 126 }; 127 128 static int upd78f0730_send_ctl(struct usb_serial_port *port, 129 const void *data, int size) 130 { 131 struct usb_device *usbdev = port->serial->dev; 132 void *buf; 133 int res; 134 135 if (size <= 0 || !data) 136 return -EINVAL; 137 138 buf = kmemdup(data, size, GFP_KERNEL); 139 if (!buf) 140 return -ENOMEM; 141 142 res = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x00, 143 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 144 0x0000, 0x0000, buf, size, USB_CTRL_SET_TIMEOUT); 145 146 kfree(buf); 147 148 if (res != size) { 149 struct device *dev = &port->dev; 150 151 dev_err(dev, "failed to send control request %02x: %d\n", 152 *(u8 *)data, res); 153 /* The maximum expected length of a transfer is 6 bytes */ 154 if (res >= 0) 155 res = -EIO; 156 157 return res; 158 } 159 160 return 0; 161 } 162 163 static int upd78f0730_port_probe(struct usb_serial_port *port) 164 { 165 struct upd78f0730_port_private *private; 166 167 private = kzalloc(sizeof(*private), GFP_KERNEL); 168 if (!private) 169 return -ENOMEM; 170 171 mutex_init(&private->lock); 172 usb_set_serial_port_data(port, private); 173 174 return 0; 175 } 176 177 static int upd78f0730_port_remove(struct usb_serial_port *port) 178 { 179 struct upd78f0730_port_private *private; 180 181 private = usb_get_serial_port_data(port); 182 mutex_destroy(&private->lock); 183 kfree(private); 184 185 return 0; 186 } 187 188 static int upd78f0730_tiocmget(struct tty_struct *tty) 189 { 190 struct device *dev = tty->dev; 191 struct upd78f0730_port_private *private; 192 struct usb_serial_port *port = tty->driver_data; 193 int signals; 194 int res; 195 196 private = usb_get_serial_port_data(port); 197 198 mutex_lock(&private->lock); 199 signals = private->line_signals; 200 mutex_unlock(&private->lock); 201 202 res = ((signals & UPD78F0730_DTR) ? TIOCM_DTR : 0) | 203 ((signals & UPD78F0730_RTS) ? TIOCM_RTS : 0); 204 205 dev_dbg(dev, "%s - res = %x\n", __func__, res); 206 207 return res; 208 } 209 210 static int upd78f0730_tiocmset(struct tty_struct *tty, 211 unsigned int set, unsigned int clear) 212 { 213 struct device *dev = tty->dev; 214 struct usb_serial_port *port = tty->driver_data; 215 struct upd78f0730_port_private *private; 216 struct upd78f0730_set_dtr_rts request; 217 int res; 218 219 private = usb_get_serial_port_data(port); 220 221 mutex_lock(&private->lock); 222 if (set & TIOCM_DTR) { 223 private->line_signals |= UPD78F0730_DTR; 224 dev_dbg(dev, "%s - set DTR\n", __func__); 225 } 226 if (set & TIOCM_RTS) { 227 private->line_signals |= UPD78F0730_RTS; 228 dev_dbg(dev, "%s - set RTS\n", __func__); 229 } 230 if (clear & TIOCM_DTR) { 231 private->line_signals &= ~UPD78F0730_DTR; 232 dev_dbg(dev, "%s - clear DTR\n", __func__); 233 } 234 if (clear & TIOCM_RTS) { 235 private->line_signals &= ~UPD78F0730_RTS; 236 dev_dbg(dev, "%s - clear RTS\n", __func__); 237 } 238 request.opcode = UPD78F0730_CMD_SET_DTR_RTS; 239 request.params = private->line_signals; 240 241 res = upd78f0730_send_ctl(port, &request, sizeof(request)); 242 mutex_unlock(&private->lock); 243 244 return res; 245 } 246 247 static void upd78f0730_break_ctl(struct tty_struct *tty, int break_state) 248 { 249 struct device *dev = tty->dev; 250 struct upd78f0730_port_private *private; 251 struct usb_serial_port *port = tty->driver_data; 252 struct upd78f0730_set_dtr_rts request; 253 254 private = usb_get_serial_port_data(port); 255 256 mutex_lock(&private->lock); 257 if (break_state) { 258 private->line_signals |= UPD78F0730_BREAK; 259 dev_dbg(dev, "%s - set BREAK\n", __func__); 260 } else { 261 private->line_signals &= ~UPD78F0730_BREAK; 262 dev_dbg(dev, "%s - clear BREAK\n", __func__); 263 } 264 request.opcode = UPD78F0730_CMD_SET_DTR_RTS; 265 request.params = private->line_signals; 266 267 upd78f0730_send_ctl(port, &request, sizeof(request)); 268 mutex_unlock(&private->lock); 269 } 270 271 static void upd78f0730_dtr_rts(struct usb_serial_port *port, int on) 272 { 273 struct tty_struct *tty = port->port.tty; 274 unsigned int set = 0; 275 unsigned int clear = 0; 276 277 if (on) 278 set = TIOCM_DTR | TIOCM_RTS; 279 else 280 clear = TIOCM_DTR | TIOCM_RTS; 281 282 upd78f0730_tiocmset(tty, set, clear); 283 } 284 285 static speed_t upd78f0730_get_baud_rate(struct tty_struct *tty) 286 { 287 const speed_t baud_rate = tty_get_baud_rate(tty); 288 static const speed_t supported[] = { 289 0, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 153600 290 }; 291 int i; 292 293 for (i = ARRAY_SIZE(supported) - 1; i >= 0; i--) { 294 if (baud_rate == supported[i]) 295 return baud_rate; 296 } 297 298 /* If the baud rate is not supported, switch to the default one */ 299 tty_encode_baud_rate(tty, 9600, 9600); 300 301 return tty_get_baud_rate(tty); 302 } 303 304 static void upd78f0730_set_termios(struct tty_struct *tty, 305 struct usb_serial_port *port, 306 struct ktermios *old_termios) 307 { 308 struct device *dev = &port->dev; 309 struct upd78f0730_line_control request; 310 speed_t baud_rate; 311 312 if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) 313 return; 314 315 if (C_BAUD(tty) == B0) 316 upd78f0730_dtr_rts(port, 0); 317 else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) 318 upd78f0730_dtr_rts(port, 1); 319 320 baud_rate = upd78f0730_get_baud_rate(tty); 321 request.opcode = UPD78F0730_CMD_LINE_CONTROL; 322 request.baud_rate = cpu_to_le32(baud_rate); 323 request.params = 0; 324 dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud_rate); 325 326 switch (C_CSIZE(tty)) { 327 case CS7: 328 request.params |= UPD78F0730_DATA_SIZE_7_BITS; 329 dev_dbg(dev, "%s - 7 data bits\n", __func__); 330 break; 331 default: 332 tty->termios.c_cflag &= ~CSIZE; 333 tty->termios.c_cflag |= CS8; 334 dev_warn(dev, "data size is not supported, using 8 bits\n"); 335 /* fall through */ 336 case CS8: 337 request.params |= UPD78F0730_DATA_SIZE_8_BITS; 338 dev_dbg(dev, "%s - 8 data bits\n", __func__); 339 break; 340 } 341 342 if (C_PARENB(tty)) { 343 if (C_PARODD(tty)) { 344 request.params |= UPD78F0730_PARITY_ODD; 345 dev_dbg(dev, "%s - odd parity\n", __func__); 346 } else { 347 request.params |= UPD78F0730_PARITY_EVEN; 348 dev_dbg(dev, "%s - even parity\n", __func__); 349 } 350 351 if (C_CMSPAR(tty)) { 352 tty->termios.c_cflag &= ~CMSPAR; 353 dev_warn(dev, "MARK/SPACE parity is not supported\n"); 354 } 355 } else { 356 request.params |= UPD78F0730_PARITY_NONE; 357 dev_dbg(dev, "%s - no parity\n", __func__); 358 } 359 360 if (C_CSTOPB(tty)) { 361 request.params |= UPD78F0730_STOP_BIT_2_BIT; 362 dev_dbg(dev, "%s - 2 stop bits\n", __func__); 363 } else { 364 request.params |= UPD78F0730_STOP_BIT_1_BIT; 365 dev_dbg(dev, "%s - 1 stop bit\n", __func__); 366 } 367 368 if (C_CRTSCTS(tty)) { 369 tty->termios.c_cflag &= ~CRTSCTS; 370 dev_warn(dev, "RTSCTS flow control is not supported\n"); 371 } 372 if (I_IXOFF(tty) || I_IXON(tty)) { 373 tty->termios.c_iflag &= ~(IXOFF | IXON); 374 dev_warn(dev, "XON/XOFF flow control is not supported\n"); 375 } 376 request.params |= UPD78F0730_FLOW_CONTROL_NONE; 377 dev_dbg(dev, "%s - no flow control\n", __func__); 378 379 upd78f0730_send_ctl(port, &request, sizeof(request)); 380 } 381 382 static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port) 383 { 384 static const struct upd78f0730_open_close request = { 385 .opcode = UPD78F0730_CMD_OPEN_CLOSE, 386 .state = UPD78F0730_PORT_OPEN 387 }; 388 int res; 389 390 res = upd78f0730_send_ctl(port, &request, sizeof(request)); 391 if (res) 392 return res; 393 394 if (tty) 395 upd78f0730_set_termios(tty, port, NULL); 396 397 return usb_serial_generic_open(tty, port); 398 } 399 400 static void upd78f0730_close(struct usb_serial_port *port) 401 { 402 static const struct upd78f0730_open_close request = { 403 .opcode = UPD78F0730_CMD_OPEN_CLOSE, 404 .state = UPD78F0730_PORT_CLOSE 405 }; 406 407 usb_serial_generic_close(port); 408 upd78f0730_send_ctl(port, &request, sizeof(request)); 409 } 410 411 static struct usb_serial_driver upd78f0730_device = { 412 .driver = { 413 .owner = THIS_MODULE, 414 .name = "upd78f0730", 415 }, 416 .id_table = id_table, 417 .num_ports = 1, 418 .port_probe = upd78f0730_port_probe, 419 .port_remove = upd78f0730_port_remove, 420 .open = upd78f0730_open, 421 .close = upd78f0730_close, 422 .set_termios = upd78f0730_set_termios, 423 .tiocmget = upd78f0730_tiocmget, 424 .tiocmset = upd78f0730_tiocmset, 425 .dtr_rts = upd78f0730_dtr_rts, 426 .break_ctl = upd78f0730_break_ctl, 427 }; 428 429 static struct usb_serial_driver * const serial_drivers[] = { 430 &upd78f0730_device, 431 NULL 432 }; 433 434 module_usb_serial_driver(serial_drivers, id_table); 435 436 MODULE_DESCRIPTION(DRIVER_DESC); 437 MODULE_AUTHOR(DRIVER_AUTHOR); 438 MODULE_LICENSE("GPL v2"); 439