Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.17-rc7 496 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * timbuart.c timberdale FPGA UART driver 4 * Copyright (c) 2009 Intel Corporation 5 */ 6 7/* Supports: 8 * Timberdale FPGA UART 9 */ 10 11#include <linux/pci.h> 12#include <linux/interrupt.h> 13#include <linux/serial_core.h> 14#include <linux/tty.h> 15#include <linux/tty_flip.h> 16#include <linux/kernel.h> 17#include <linux/platform_device.h> 18#include <linux/ioport.h> 19#include <linux/slab.h> 20#include <linux/module.h> 21 22#include "timbuart.h" 23 24struct timbuart_port { 25 struct uart_port port; 26 struct tasklet_struct tasklet; 27 int usedma; 28 u32 last_ier; 29 struct platform_device *dev; 30}; 31 32static int baudrates[] = {9600, 19200, 38400, 57600, 115200, 230400, 460800, 33 921600, 1843200, 3250000}; 34 35static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier); 36 37static irqreturn_t timbuart_handleinterrupt(int irq, void *devid); 38 39static void timbuart_stop_rx(struct uart_port *port) 40{ 41 /* spin lock held by upper layer, disable all RX interrupts */ 42 u32 ier = ioread32(port->membase + TIMBUART_IER) & ~RXFLAGS; 43 iowrite32(ier, port->membase + TIMBUART_IER); 44} 45 46static void timbuart_stop_tx(struct uart_port *port) 47{ 48 /* spinlock held by upper layer, disable TX interrupt */ 49 u32 ier = ioread32(port->membase + TIMBUART_IER) & ~TXBAE; 50 iowrite32(ier, port->membase + TIMBUART_IER); 51} 52 53static void timbuart_start_tx(struct uart_port *port) 54{ 55 struct timbuart_port *uart = 56 container_of(port, struct timbuart_port, port); 57 58 /* do not transfer anything here -> fire off the tasklet */ 59 tasklet_schedule(&uart->tasklet); 60} 61 62static unsigned int timbuart_tx_empty(struct uart_port *port) 63{ 64 u32 isr = ioread32(port->membase + TIMBUART_ISR); 65 66 return (isr & TXBE) ? TIOCSER_TEMT : 0; 67} 68 69static void timbuart_flush_buffer(struct uart_port *port) 70{ 71 if (!timbuart_tx_empty(port)) { 72 u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | 73 TIMBUART_CTRL_FLSHTX; 74 75 iowrite8(ctl, port->membase + TIMBUART_CTRL); 76 iowrite32(TXBF, port->membase + TIMBUART_ISR); 77 } 78} 79 80static void timbuart_rx_chars(struct uart_port *port) 81{ 82 struct tty_port *tport = &port->state->port; 83 84 while (ioread32(port->membase + TIMBUART_ISR) & RXDP) { 85 u8 ch = ioread8(port->membase + TIMBUART_RXFIFO); 86 port->icount.rx++; 87 tty_insert_flip_char(tport, ch, TTY_NORMAL); 88 } 89 90 tty_flip_buffer_push(tport); 91 92 dev_dbg(port->dev, "%s - total read %d bytes\n", 93 __func__, port->icount.rx); 94} 95 96static void timbuart_tx_chars(struct uart_port *port) 97{ 98 unsigned char ch; 99 100 while (!(ioread32(port->membase + TIMBUART_ISR) & TXBF) && 101 uart_fifo_get(port, &ch)) 102 iowrite8(ch, port->membase + TIMBUART_TXFIFO); 103 104 dev_dbg(port->dev, 105 "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n", 106 __func__, 107 port->icount.tx, 108 ioread8(port->membase + TIMBUART_CTRL), 109 port->mctrl & TIOCM_RTS, 110 ioread8(port->membase + TIMBUART_BAUDRATE)); 111} 112 113static void timbuart_handle_tx_port(struct uart_port *port, u32 isr, u32 *ier) 114{ 115 struct timbuart_port *uart = 116 container_of(port, struct timbuart_port, port); 117 struct tty_port *tport = &port->state->port; 118 119 if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) 120 return; 121 122 if (port->x_char) 123 return; 124 125 if (isr & TXFLAGS) { 126 timbuart_tx_chars(port); 127 /* clear all TX interrupts */ 128 iowrite32(TXFLAGS, port->membase + TIMBUART_ISR); 129 130 if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) 131 uart_write_wakeup(port); 132 } else 133 /* Re-enable any tx interrupt */ 134 *ier |= uart->last_ier & TXFLAGS; 135 136 /* enable interrupts if there are chars in the transmit buffer, 137 * Or if we delivered some bytes and want the almost empty interrupt 138 * we wake up the upper layer later when we got the interrupt 139 * to give it some time to go out... 140 */ 141 if (!kfifo_is_empty(&tport->xmit_fifo)) 142 *ier |= TXBAE; 143 144 dev_dbg(port->dev, "%s - leaving\n", __func__); 145} 146 147static void timbuart_handle_rx_port(struct uart_port *port, u32 isr, u32 *ier) 148{ 149 if (isr & RXFLAGS) { 150 /* Some RX status is set */ 151 if (isr & RXBF) { 152 u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | 153 TIMBUART_CTRL_FLSHRX; 154 iowrite8(ctl, port->membase + TIMBUART_CTRL); 155 port->icount.overrun++; 156 } else if (isr & (RXDP)) 157 timbuart_rx_chars(port); 158 159 /* ack all RX interrupts */ 160 iowrite32(RXFLAGS, port->membase + TIMBUART_ISR); 161 } 162 163 /* always have the RX interrupts enabled */ 164 *ier |= RXBAF | RXBF | RXTT; 165 166 dev_dbg(port->dev, "%s - leaving\n", __func__); 167} 168 169static void timbuart_tasklet(struct tasklet_struct *t) 170{ 171 struct timbuart_port *uart = from_tasklet(uart, t, tasklet); 172 u32 isr, ier = 0; 173 174 uart_port_lock(&uart->port); 175 176 isr = ioread32(uart->port.membase + TIMBUART_ISR); 177 dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr); 178 179 if (!uart->usedma) 180 timbuart_handle_tx_port(&uart->port, isr, &ier); 181 182 timbuart_mctrl_check(&uart->port, isr, &ier); 183 184 if (!uart->usedma) 185 timbuart_handle_rx_port(&uart->port, isr, &ier); 186 187 iowrite32(ier, uart->port.membase + TIMBUART_IER); 188 189 uart_port_unlock(&uart->port); 190 dev_dbg(uart->port.dev, "%s leaving\n", __func__); 191} 192 193static unsigned int timbuart_get_mctrl(struct uart_port *port) 194{ 195 u8 cts = ioread8(port->membase + TIMBUART_CTRL); 196 dev_dbg(port->dev, "%s - cts %x\n", __func__, cts); 197 198 if (cts & TIMBUART_CTRL_CTS) 199 return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; 200 else 201 return TIOCM_DSR | TIOCM_CAR; 202} 203 204static void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl) 205{ 206 dev_dbg(port->dev, "%s - %x\n", __func__, mctrl); 207 208 if (mctrl & TIOCM_RTS) 209 iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL); 210 else 211 iowrite8(0, port->membase + TIMBUART_CTRL); 212} 213 214static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier) 215{ 216 unsigned int cts; 217 218 if (isr & CTS_DELTA) { 219 /* ack */ 220 iowrite32(CTS_DELTA, port->membase + TIMBUART_ISR); 221 cts = timbuart_get_mctrl(port); 222 uart_handle_cts_change(port, cts & TIOCM_CTS); 223 wake_up_interruptible(&port->state->port.delta_msr_wait); 224 } 225 226 *ier |= CTS_DELTA; 227} 228 229static void timbuart_break_ctl(struct uart_port *port, int ctl) 230{ 231 /* N/A */ 232} 233 234static int timbuart_startup(struct uart_port *port) 235{ 236 struct timbuart_port *uart = 237 container_of(port, struct timbuart_port, port); 238 239 dev_dbg(port->dev, "%s\n", __func__); 240 241 iowrite8(TIMBUART_CTRL_FLSHRX, port->membase + TIMBUART_CTRL); 242 iowrite32(0x1ff, port->membase + TIMBUART_ISR); 243 /* Enable all but TX interrupts */ 244 iowrite32(RXBAF | RXBF | RXTT | CTS_DELTA, 245 port->membase + TIMBUART_IER); 246 247 return request_irq(port->irq, timbuart_handleinterrupt, IRQF_SHARED, 248 "timb-uart", uart); 249} 250 251static void timbuart_shutdown(struct uart_port *port) 252{ 253 struct timbuart_port *uart = 254 container_of(port, struct timbuart_port, port); 255 dev_dbg(port->dev, "%s\n", __func__); 256 free_irq(port->irq, uart); 257 iowrite32(0, port->membase + TIMBUART_IER); 258 259 timbuart_flush_buffer(port); 260} 261 262static int get_bindex(int baud) 263{ 264 int i; 265 266 for (i = 0; i < ARRAY_SIZE(baudrates); i++) 267 if (baud <= baudrates[i]) 268 return i; 269 270 return -1; 271} 272 273static void timbuart_set_termios(struct uart_port *port, 274 struct ktermios *termios, 275 const struct ktermios *old) 276{ 277 unsigned int baud; 278 short bindex; 279 unsigned long flags; 280 281 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); 282 bindex = get_bindex(baud); 283 dev_dbg(port->dev, "%s - bindex %d\n", __func__, bindex); 284 285 if (bindex < 0) 286 bindex = 0; 287 baud = baudrates[bindex]; 288 289 /* The serial layer calls into this once with old = NULL when setting 290 up initially */ 291 if (old) 292 tty_termios_copy_hw(termios, old); 293 tty_termios_encode_baud_rate(termios, baud, baud); 294 295 uart_port_lock_irqsave(port, &flags); 296 iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE); 297 uart_update_timeout(port, termios->c_cflag, baud); 298 uart_port_unlock_irqrestore(port, flags); 299} 300 301static const char *timbuart_type(struct uart_port *port) 302{ 303 return port->type == PORT_UNKNOWN ? "timbuart" : NULL; 304} 305 306/* We do not request/release mappings of the registers here, 307 * currently it's done in the proble function. 308 */ 309static void timbuart_release_port(struct uart_port *port) 310{ 311 struct platform_device *pdev = to_platform_device(port->dev); 312 int size = 313 resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0)); 314 315 if (port->flags & UPF_IOREMAP) { 316 iounmap(port->membase); 317 port->membase = NULL; 318 } 319 320 release_mem_region(port->mapbase, size); 321} 322 323static int timbuart_request_port(struct uart_port *port) 324{ 325 struct platform_device *pdev = to_platform_device(port->dev); 326 int size = 327 resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0)); 328 329 if (!request_mem_region(port->mapbase, size, "timb-uart")) 330 return -EBUSY; 331 332 if (port->flags & UPF_IOREMAP) { 333 port->membase = ioremap(port->mapbase, size); 334 if (port->membase == NULL) { 335 release_mem_region(port->mapbase, size); 336 return -ENOMEM; 337 } 338 } 339 340 return 0; 341} 342 343static irqreturn_t timbuart_handleinterrupt(int irq, void *devid) 344{ 345 struct timbuart_port *uart = (struct timbuart_port *)devid; 346 347 if (ioread8(uart->port.membase + TIMBUART_IPR)) { 348 uart->last_ier = ioread32(uart->port.membase + TIMBUART_IER); 349 350 /* disable interrupts, the tasklet enables them again */ 351 iowrite32(0, uart->port.membase + TIMBUART_IER); 352 353 /* fire off bottom half */ 354 tasklet_schedule(&uart->tasklet); 355 356 return IRQ_HANDLED; 357 } else 358 return IRQ_NONE; 359} 360 361/* 362 * Configure/autoconfigure the port. 363 */ 364static void timbuart_config_port(struct uart_port *port, int flags) 365{ 366 if (flags & UART_CONFIG_TYPE) { 367 port->type = PORT_TIMBUART; 368 timbuart_request_port(port); 369 } 370} 371 372static int timbuart_verify_port(struct uart_port *port, 373 struct serial_struct *ser) 374{ 375 /* we don't want the core code to modify any port params */ 376 return -EINVAL; 377} 378 379static const struct uart_ops timbuart_ops = { 380 .tx_empty = timbuart_tx_empty, 381 .set_mctrl = timbuart_set_mctrl, 382 .get_mctrl = timbuart_get_mctrl, 383 .stop_tx = timbuart_stop_tx, 384 .start_tx = timbuart_start_tx, 385 .flush_buffer = timbuart_flush_buffer, 386 .stop_rx = timbuart_stop_rx, 387 .break_ctl = timbuart_break_ctl, 388 .startup = timbuart_startup, 389 .shutdown = timbuart_shutdown, 390 .set_termios = timbuart_set_termios, 391 .type = timbuart_type, 392 .release_port = timbuart_release_port, 393 .request_port = timbuart_request_port, 394 .config_port = timbuart_config_port, 395 .verify_port = timbuart_verify_port 396}; 397 398static struct uart_driver timbuart_driver = { 399 .owner = THIS_MODULE, 400 .driver_name = "timberdale_uart", 401 .dev_name = "ttyTU", 402 .major = TIMBUART_MAJOR, 403 .minor = TIMBUART_MINOR, 404 .nr = 1 405}; 406 407static int timbuart_probe(struct platform_device *dev) 408{ 409 int err, irq; 410 struct timbuart_port *uart; 411 struct resource *iomem; 412 413 dev_dbg(&dev->dev, "%s\n", __func__); 414 415 uart = kzalloc(sizeof(*uart), GFP_KERNEL); 416 if (!uart) { 417 err = -EINVAL; 418 goto err_mem; 419 } 420 421 uart->usedma = 0; 422 423 uart->port.uartclk = 3250000 * 16; 424 uart->port.fifosize = TIMBUART_FIFO_SIZE; 425 uart->port.regshift = 2; 426 uart->port.iotype = UPIO_MEM; 427 uart->port.ops = &timbuart_ops; 428 uart->port.irq = 0; 429 uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; 430 uart->port.line = 0; 431 uart->port.dev = &dev->dev; 432 433 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); 434 if (!iomem) { 435 err = -ENOMEM; 436 goto err_register; 437 } 438 uart->port.mapbase = iomem->start; 439 uart->port.membase = NULL; 440 441 irq = platform_get_irq(dev, 0); 442 if (irq < 0) { 443 err = -EINVAL; 444 goto err_register; 445 } 446 uart->port.irq = irq; 447 448 tasklet_setup(&uart->tasklet, timbuart_tasklet); 449 450 err = uart_register_driver(&timbuart_driver); 451 if (err) 452 goto err_register; 453 454 err = uart_add_one_port(&timbuart_driver, &uart->port); 455 if (err) 456 goto err_add_port; 457 458 platform_set_drvdata(dev, uart); 459 460 return 0; 461 462err_add_port: 463 uart_unregister_driver(&timbuart_driver); 464err_register: 465 kfree(uart); 466err_mem: 467 printk(KERN_ERR "timberdale: Failed to register Timberdale UART: %d\n", 468 err); 469 470 return err; 471} 472 473static void timbuart_remove(struct platform_device *dev) 474{ 475 struct timbuart_port *uart = platform_get_drvdata(dev); 476 477 tasklet_kill(&uart->tasklet); 478 uart_remove_one_port(&timbuart_driver, &uart->port); 479 uart_unregister_driver(&timbuart_driver); 480 kfree(uart); 481} 482 483static struct platform_driver timbuart_platform_driver = { 484 .driver = { 485 .name = "timb-uart", 486 }, 487 .probe = timbuart_probe, 488 .remove = timbuart_remove, 489}; 490 491module_platform_driver(timbuart_platform_driver); 492 493MODULE_DESCRIPTION("Timberdale UART driver"); 494MODULE_LICENSE("GPL v2"); 495MODULE_ALIAS("platform:timb-uart"); 496