1 // SPDX-License-Identifier: GPL-2.0+ 2 /****************************************************************************/ 3 4 /* 5 * mcf.c -- Freescale ColdFire UART driver 6 * 7 * (C) Copyright 2003-2007, Greg Ungerer <gerg@uclinux.org> 8 */ 9 10 /****************************************************************************/ 11 12 #include <linux/kernel.h> 13 #include <linux/init.h> 14 #include <linux/interrupt.h> 15 #include <linux/module.h> 16 #include <linux/console.h> 17 #include <linux/tty.h> 18 #include <linux/tty_flip.h> 19 #include <linux/serial.h> 20 #include <linux/serial_core.h> 21 #include <linux/io.h> 22 #include <linux/uaccess.h> 23 #include <linux/platform_device.h> 24 #include <asm/coldfire.h> 25 #include <asm/mcfsim.h> 26 #include <asm/mcfuart.h> 27 #include <asm/nettel.h> 28 29 /****************************************************************************/ 30 31 /* 32 * Some boards implement the DTR/DCD lines using GPIO lines, most 33 * don't. Dummy out the access macros for those that don't. Those 34 * that do should define these macros somewhere in there board 35 * specific inlude files. 36 */ 37 #if !defined(mcf_getppdcd) 38 #define mcf_getppdcd(p) (1) 39 #endif 40 #if !defined(mcf_getppdtr) 41 #define mcf_getppdtr(p) (1) 42 #endif 43 #if !defined(mcf_setppdtr) 44 #define mcf_setppdtr(p, v) do { } while (0) 45 #endif 46 47 /****************************************************************************/ 48 49 /* 50 * Local per-uart structure. 51 */ 52 struct mcf_uart { 53 struct uart_port port; 54 unsigned int sigs; /* Local copy of line sigs */ 55 unsigned char imr; /* Local IMR mirror */ 56 }; 57 58 /****************************************************************************/ 59 60 static unsigned int mcf_tx_empty(struct uart_port *port) 61 { 62 return (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXEMPTY) ? 63 TIOCSER_TEMT : 0; 64 } 65 66 /****************************************************************************/ 67 68 static unsigned int mcf_get_mctrl(struct uart_port *port) 69 { 70 struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 71 unsigned int sigs; 72 73 sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ? 74 0 : TIOCM_CTS; 75 sigs |= (pp->sigs & TIOCM_RTS); 76 sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0); 77 sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0); 78 79 return sigs; 80 } 81 82 /****************************************************************************/ 83 84 static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) 85 { 86 struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 87 88 pp->sigs = sigs; 89 mcf_setppdtr(port->line, (sigs & TIOCM_DTR)); 90 if (sigs & TIOCM_RTS) 91 writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); 92 else 93 writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0); 94 } 95 96 /****************************************************************************/ 97 98 static void mcf_start_tx(struct uart_port *port) 99 { 100 struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 101 102 if (port->rs485.flags & SER_RS485_ENABLED) { 103 /* Enable Transmitter */ 104 writeb(MCFUART_UCR_TXENABLE, port->membase + MCFUART_UCR); 105 /* Manually assert RTS */ 106 writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); 107 } 108 pp->imr |= MCFUART_UIR_TXREADY; 109 writeb(pp->imr, port->membase + MCFUART_UIMR); 110 } 111 112 /****************************************************************************/ 113 114 static void mcf_stop_tx(struct uart_port *port) 115 { 116 struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 117 118 pp->imr &= ~MCFUART_UIR_TXREADY; 119 writeb(pp->imr, port->membase + MCFUART_UIMR); 120 } 121 122 /****************************************************************************/ 123 124 static void mcf_stop_rx(struct uart_port *port) 125 { 126 struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 127 128 pp->imr &= ~MCFUART_UIR_RXREADY; 129 writeb(pp->imr, port->membase + MCFUART_UIMR); 130 } 131 132 /****************************************************************************/ 133 134 static void mcf_break_ctl(struct uart_port *port, int break_state) 135 { 136 unsigned long flags; 137 138 spin_lock_irqsave(&port->lock, flags); 139 if (break_state == -1) 140 writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR); 141 else 142 writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR); 143 spin_unlock_irqrestore(&port->lock, flags); 144 } 145 146 /****************************************************************************/ 147 148 static int mcf_startup(struct uart_port *port) 149 { 150 struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 151 unsigned long flags; 152 153 spin_lock_irqsave(&port->lock, flags); 154 155 /* Reset UART, get it into known state... */ 156 writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 157 writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); 158 159 /* Enable the UART transmitter and receiver */ 160 writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE, 161 port->membase + MCFUART_UCR); 162 163 /* Enable RX interrupts now */ 164 pp->imr = MCFUART_UIR_RXREADY; 165 writeb(pp->imr, port->membase + MCFUART_UIMR); 166 167 spin_unlock_irqrestore(&port->lock, flags); 168 169 return 0; 170 } 171 172 /****************************************************************************/ 173 174 static void mcf_shutdown(struct uart_port *port) 175 { 176 struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 177 unsigned long flags; 178 179 spin_lock_irqsave(&port->lock, flags); 180 181 /* Disable all interrupts now */ 182 pp->imr = 0; 183 writeb(pp->imr, port->membase + MCFUART_UIMR); 184 185 /* Disable UART transmitter and receiver */ 186 writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 187 writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); 188 189 spin_unlock_irqrestore(&port->lock, flags); 190 } 191 192 /****************************************************************************/ 193 194 static void mcf_set_termios(struct uart_port *port, struct ktermios *termios, 195 struct ktermios *old) 196 { 197 unsigned long flags; 198 unsigned int baud, baudclk; 199 #if defined(CONFIG_M5272) 200 unsigned int baudfr; 201 #endif 202 unsigned char mr1, mr2; 203 204 baud = uart_get_baud_rate(port, termios, old, 0, 230400); 205 #if defined(CONFIG_M5272) 206 baudclk = (MCF_BUSCLK / baud) / 32; 207 baudfr = (((MCF_BUSCLK / baud) + 1) / 2) % 16; 208 #else 209 baudclk = ((MCF_BUSCLK / baud) + 16) / 32; 210 #endif 211 212 mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR; 213 mr2 = 0; 214 215 switch (termios->c_cflag & CSIZE) { 216 case CS5: mr1 |= MCFUART_MR1_CS5; break; 217 case CS6: mr1 |= MCFUART_MR1_CS6; break; 218 case CS7: mr1 |= MCFUART_MR1_CS7; break; 219 case CS8: 220 default: mr1 |= MCFUART_MR1_CS8; break; 221 } 222 223 if (termios->c_cflag & PARENB) { 224 if (termios->c_cflag & CMSPAR) { 225 if (termios->c_cflag & PARODD) 226 mr1 |= MCFUART_MR1_PARITYMARK; 227 else 228 mr1 |= MCFUART_MR1_PARITYSPACE; 229 } else { 230 if (termios->c_cflag & PARODD) 231 mr1 |= MCFUART_MR1_PARITYODD; 232 else 233 mr1 |= MCFUART_MR1_PARITYEVEN; 234 } 235 } else { 236 mr1 |= MCFUART_MR1_PARITYNONE; 237 } 238 239 /* 240 * FIXME: port->read_status_mask and port->ignore_status_mask 241 * need to be initialized based on termios settings for 242 * INPCK, IGNBRK, IGNPAR, PARMRK, BRKINT 243 */ 244 245 if (termios->c_cflag & CSTOPB) 246 mr2 |= MCFUART_MR2_STOP2; 247 else 248 mr2 |= MCFUART_MR2_STOP1; 249 250 if (termios->c_cflag & CRTSCTS) { 251 mr1 |= MCFUART_MR1_RXRTS; 252 mr2 |= MCFUART_MR2_TXCTS; 253 } 254 255 spin_lock_irqsave(&port->lock, flags); 256 if (port->rs485.flags & SER_RS485_ENABLED) { 257 dev_dbg(port->dev, "Setting UART to RS485\n"); 258 mr2 |= MCFUART_MR2_TXRTS; 259 } 260 261 uart_update_timeout(port, termios->c_cflag, baud); 262 writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); 263 writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); 264 writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR); 265 writeb(mr1, port->membase + MCFUART_UMR); 266 writeb(mr2, port->membase + MCFUART_UMR); 267 writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1); 268 writeb((baudclk & 0xff), port->membase + MCFUART_UBG2); 269 #if defined(CONFIG_M5272) 270 writeb((baudfr & 0x0f), port->membase + MCFUART_UFPD); 271 #endif 272 writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER, 273 port->membase + MCFUART_UCSR); 274 writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE, 275 port->membase + MCFUART_UCR); 276 spin_unlock_irqrestore(&port->lock, flags); 277 } 278 279 /****************************************************************************/ 280 281 static void mcf_rx_chars(struct mcf_uart *pp) 282 { 283 struct uart_port *port = &pp->port; 284 unsigned char status, ch, flag; 285 286 while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) { 287 ch = readb(port->membase + MCFUART_URB); 288 flag = TTY_NORMAL; 289 port->icount.rx++; 290 291 if (status & MCFUART_USR_RXERR) { 292 writeb(MCFUART_UCR_CMDRESETERR, 293 port->membase + MCFUART_UCR); 294 295 if (status & MCFUART_USR_RXBREAK) { 296 port->icount.brk++; 297 if (uart_handle_break(port)) 298 continue; 299 } else if (status & MCFUART_USR_RXPARITY) { 300 port->icount.parity++; 301 } else if (status & MCFUART_USR_RXOVERRUN) { 302 port->icount.overrun++; 303 } else if (status & MCFUART_USR_RXFRAMING) { 304 port->icount.frame++; 305 } 306 307 status &= port->read_status_mask; 308 309 if (status & MCFUART_USR_RXBREAK) 310 flag = TTY_BREAK; 311 else if (status & MCFUART_USR_RXPARITY) 312 flag = TTY_PARITY; 313 else if (status & MCFUART_USR_RXFRAMING) 314 flag = TTY_FRAME; 315 } 316 317 if (uart_handle_sysrq_char(port, ch)) 318 continue; 319 uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag); 320 } 321 322 tty_flip_buffer_push(&port->state->port); 323 } 324 325 /****************************************************************************/ 326 327 static void mcf_tx_chars(struct mcf_uart *pp) 328 { 329 struct uart_port *port = &pp->port; 330 struct circ_buf *xmit = &port->state->xmit; 331 332 if (port->x_char) { 333 /* Send special char - probably flow control */ 334 writeb(port->x_char, port->membase + MCFUART_UTB); 335 port->x_char = 0; 336 port->icount.tx++; 337 return; 338 } 339 340 while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) { 341 if (uart_circ_empty(xmit)) 342 break; 343 writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB); 344 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1); 345 port->icount.tx++; 346 } 347 348 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 349 uart_write_wakeup(port); 350 351 if (uart_circ_empty(xmit)) { 352 mcf_stop_tx(port); 353 /* Disable TX to negate RTS automatically */ 354 if (port->rs485.flags & SER_RS485_ENABLED) 355 writeb(MCFUART_UCR_TXDISABLE, 356 port->membase + MCFUART_UCR); 357 } 358 } 359 360 /****************************************************************************/ 361 362 static irqreturn_t mcf_interrupt(int irq, void *data) 363 { 364 struct uart_port *port = data; 365 struct mcf_uart *pp = container_of(port, struct mcf_uart, port); 366 unsigned int isr; 367 irqreturn_t ret = IRQ_NONE; 368 369 isr = readb(port->membase + MCFUART_UISR) & pp->imr; 370 371 spin_lock(&port->lock); 372 if (isr & MCFUART_UIR_RXREADY) { 373 mcf_rx_chars(pp); 374 ret = IRQ_HANDLED; 375 } 376 if (isr & MCFUART_UIR_TXREADY) { 377 mcf_tx_chars(pp); 378 ret = IRQ_HANDLED; 379 } 380 spin_unlock(&port->lock); 381 382 return ret; 383 } 384 385 /****************************************************************************/ 386 387 static void mcf_config_port(struct uart_port *port, int flags) 388 { 389 port->type = PORT_MCF; 390 port->fifosize = MCFUART_TXFIFOSIZE; 391 392 /* Clear mask, so no surprise interrupts. */ 393 writeb(0, port->membase + MCFUART_UIMR); 394 395 if (request_irq(port->irq, mcf_interrupt, 0, "UART", port)) 396 printk(KERN_ERR "MCF: unable to attach ColdFire UART %d " 397 "interrupt vector=%d\n", port->line, port->irq); 398 } 399 400 /****************************************************************************/ 401 402 static const char *mcf_type(struct uart_port *port) 403 { 404 return (port->type == PORT_MCF) ? "ColdFire UART" : NULL; 405 } 406 407 /****************************************************************************/ 408 409 static int mcf_request_port(struct uart_port *port) 410 { 411 /* UARTs always present */ 412 return 0; 413 } 414 415 /****************************************************************************/ 416 417 static void mcf_release_port(struct uart_port *port) 418 { 419 /* Nothing to release... */ 420 } 421 422 /****************************************************************************/ 423 424 static int mcf_verify_port(struct uart_port *port, struct serial_struct *ser) 425 { 426 if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MCF)) 427 return -EINVAL; 428 return 0; 429 } 430 431 /****************************************************************************/ 432 433 /* Enable or disable the RS485 support */ 434 static int mcf_config_rs485(struct uart_port *port, struct ktermios *termios, 435 struct serial_rs485 *rs485) 436 { 437 unsigned char mr1, mr2; 438 439 /* Get mode registers */ 440 mr1 = readb(port->membase + MCFUART_UMR); 441 mr2 = readb(port->membase + MCFUART_UMR); 442 if (rs485->flags & SER_RS485_ENABLED) { 443 dev_dbg(port->dev, "Setting UART to RS485\n"); 444 /* Automatically negate RTS after TX completes */ 445 mr2 |= MCFUART_MR2_TXRTS; 446 } else { 447 dev_dbg(port->dev, "Setting UART to RS232\n"); 448 mr2 &= ~MCFUART_MR2_TXRTS; 449 } 450 writeb(mr1, port->membase + MCFUART_UMR); 451 writeb(mr2, port->membase + MCFUART_UMR); 452 453 return 0; 454 } 455 456 static const struct serial_rs485 mcf_rs485_supported = { 457 .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND, 458 }; 459 460 /****************************************************************************/ 461 462 /* 463 * Define the basic serial functions we support. 464 */ 465 static const struct uart_ops mcf_uart_ops = { 466 .tx_empty = mcf_tx_empty, 467 .get_mctrl = mcf_get_mctrl, 468 .set_mctrl = mcf_set_mctrl, 469 .start_tx = mcf_start_tx, 470 .stop_tx = mcf_stop_tx, 471 .stop_rx = mcf_stop_rx, 472 .break_ctl = mcf_break_ctl, 473 .startup = mcf_startup, 474 .shutdown = mcf_shutdown, 475 .set_termios = mcf_set_termios, 476 .type = mcf_type, 477 .request_port = mcf_request_port, 478 .release_port = mcf_release_port, 479 .config_port = mcf_config_port, 480 .verify_port = mcf_verify_port, 481 }; 482 483 static struct mcf_uart mcf_ports[4]; 484 485 #define MCF_MAXPORTS ARRAY_SIZE(mcf_ports) 486 487 /****************************************************************************/ 488 #if defined(CONFIG_SERIAL_MCF_CONSOLE) 489 /****************************************************************************/ 490 491 int __init early_mcf_setup(struct mcf_platform_uart *platp) 492 { 493 struct uart_port *port; 494 int i; 495 496 for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { 497 port = &mcf_ports[i].port; 498 499 port->line = i; 500 port->type = PORT_MCF; 501 port->mapbase = platp[i].mapbase; 502 port->membase = (platp[i].membase) ? platp[i].membase : 503 (unsigned char __iomem *) port->mapbase; 504 port->iotype = SERIAL_IO_MEM; 505 port->irq = platp[i].irq; 506 port->uartclk = MCF_BUSCLK; 507 port->flags = UPF_BOOT_AUTOCONF; 508 port->rs485_config = mcf_config_rs485; 509 port->rs485_supported = &mcf_rs485_supported; 510 port->ops = &mcf_uart_ops; 511 } 512 513 return 0; 514 } 515 516 /****************************************************************************/ 517 518 static void mcf_console_putc(struct console *co, const char c) 519 { 520 struct uart_port *port = &(mcf_ports + co->index)->port; 521 int i; 522 523 for (i = 0; (i < 0x10000); i++) { 524 if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) 525 break; 526 } 527 writeb(c, port->membase + MCFUART_UTB); 528 for (i = 0; (i < 0x10000); i++) { 529 if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) 530 break; 531 } 532 } 533 534 /****************************************************************************/ 535 536 static void mcf_console_write(struct console *co, const char *s, unsigned int count) 537 { 538 for (; (count); count--, s++) { 539 mcf_console_putc(co, *s); 540 if (*s == '\n') 541 mcf_console_putc(co, '\r'); 542 } 543 } 544 545 /****************************************************************************/ 546 547 static int __init mcf_console_setup(struct console *co, char *options) 548 { 549 struct uart_port *port; 550 int baud = CONFIG_SERIAL_MCF_BAUDRATE; 551 int bits = 8; 552 int parity = 'n'; 553 int flow = 'n'; 554 555 if ((co->index < 0) || (co->index >= MCF_MAXPORTS)) 556 co->index = 0; 557 port = &mcf_ports[co->index].port; 558 if (port->membase == 0) 559 return -ENODEV; 560 561 if (options) 562 uart_parse_options(options, &baud, &parity, &bits, &flow); 563 564 return uart_set_options(port, co, baud, parity, bits, flow); 565 } 566 567 /****************************************************************************/ 568 569 static struct uart_driver mcf_driver; 570 571 static struct console mcf_console = { 572 .name = "ttyS", 573 .write = mcf_console_write, 574 .device = uart_console_device, 575 .setup = mcf_console_setup, 576 .flags = CON_PRINTBUFFER, 577 .index = -1, 578 .data = &mcf_driver, 579 }; 580 581 static int __init mcf_console_init(void) 582 { 583 register_console(&mcf_console); 584 return 0; 585 } 586 587 console_initcall(mcf_console_init); 588 589 #define MCF_CONSOLE &mcf_console 590 591 /****************************************************************************/ 592 #else 593 /****************************************************************************/ 594 595 #define MCF_CONSOLE NULL 596 597 /****************************************************************************/ 598 #endif /* CONFIG_SERIAL_MCF_CONSOLE */ 599 /****************************************************************************/ 600 601 /* 602 * Define the mcf UART driver structure. 603 */ 604 static struct uart_driver mcf_driver = { 605 .owner = THIS_MODULE, 606 .driver_name = "mcf", 607 .dev_name = "ttyS", 608 .major = TTY_MAJOR, 609 .minor = 64, 610 .nr = MCF_MAXPORTS, 611 .cons = MCF_CONSOLE, 612 }; 613 614 /****************************************************************************/ 615 616 static int mcf_probe(struct platform_device *pdev) 617 { 618 struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); 619 struct uart_port *port; 620 int i; 621 622 for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { 623 port = &mcf_ports[i].port; 624 625 port->line = i; 626 port->type = PORT_MCF; 627 port->mapbase = platp[i].mapbase; 628 port->membase = (platp[i].membase) ? platp[i].membase : 629 (unsigned char __iomem *) platp[i].mapbase; 630 port->dev = &pdev->dev; 631 port->iotype = SERIAL_IO_MEM; 632 port->irq = platp[i].irq; 633 port->uartclk = MCF_BUSCLK; 634 port->ops = &mcf_uart_ops; 635 port->flags = UPF_BOOT_AUTOCONF; 636 port->rs485_config = mcf_config_rs485; 637 port->rs485_supported = &mcf_rs485_supported; 638 port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); 639 640 uart_add_one_port(&mcf_driver, port); 641 } 642 643 return 0; 644 } 645 646 /****************************************************************************/ 647 648 static int mcf_remove(struct platform_device *pdev) 649 { 650 struct uart_port *port; 651 int i; 652 653 for (i = 0; (i < MCF_MAXPORTS); i++) { 654 port = &mcf_ports[i].port; 655 if (port) 656 uart_remove_one_port(&mcf_driver, port); 657 } 658 659 return 0; 660 } 661 662 /****************************************************************************/ 663 664 static struct platform_driver mcf_platform_driver = { 665 .probe = mcf_probe, 666 .remove = mcf_remove, 667 .driver = { 668 .name = "mcfuart", 669 }, 670 }; 671 672 /****************************************************************************/ 673 674 static int __init mcf_init(void) 675 { 676 int rc; 677 678 printk("ColdFire internal UART serial driver\n"); 679 680 rc = uart_register_driver(&mcf_driver); 681 if (rc) 682 return rc; 683 rc = platform_driver_register(&mcf_platform_driver); 684 if (rc) { 685 uart_unregister_driver(&mcf_driver); 686 return rc; 687 } 688 return 0; 689 } 690 691 /****************************************************************************/ 692 693 static void __exit mcf_exit(void) 694 { 695 platform_driver_unregister(&mcf_platform_driver); 696 uart_unregister_driver(&mcf_driver); 697 } 698 699 /****************************************************************************/ 700 701 module_init(mcf_init); 702 module_exit(mcf_exit); 703 704 MODULE_AUTHOR("Greg Ungerer <gerg@uclinux.org>"); 705 MODULE_DESCRIPTION("Freescale ColdFire UART driver"); 706 MODULE_LICENSE("GPL"); 707 MODULE_ALIAS("platform:mcfuart"); 708 709 /****************************************************************************/ 710