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

serial: mps2-uart: support combined irq

It turns out that some designs went for implementing only combined
interrupt for rx, tx and overrun, which is currently not supported
by the driver. Support of combined irq is built on top of existent
irq handlers and activated automatically if only single irq was
specified in device tree.

Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Vladimir Murzin and committed by
Greg Kroah-Hartman
775ea4ea 9f25e07b

+65 -26
+65 -26
drivers/tty/serial/mps2-uart.c
··· 66 66 67 67 #define MPS2_MAX_PORTS 3 68 68 69 + #define UART_PORT_COMBINED_IRQ BIT(0) 70 + 69 71 struct mps2_uart_port { 70 72 struct uart_port port; 71 73 struct clk *clk; 72 74 unsigned int tx_irq; 73 75 unsigned int rx_irq; 76 + unsigned int flags; 74 77 }; 75 78 76 79 static inline struct mps2_uart_port *to_mps2_port(struct uart_port *port) ··· 268 265 return handled; 269 266 } 270 267 268 + static irqreturn_t mps2_uart_combinedirq(int irq, void *data) 269 + { 270 + if (mps2_uart_rxirq(irq, data) == IRQ_HANDLED) 271 + return IRQ_HANDLED; 272 + 273 + if (mps2_uart_txirq(irq, data) == IRQ_HANDLED) 274 + return IRQ_HANDLED; 275 + 276 + if (mps2_uart_oerrirq(irq, data) == IRQ_HANDLED) 277 + return IRQ_HANDLED; 278 + 279 + return IRQ_NONE; 280 + } 281 + 271 282 static int mps2_uart_startup(struct uart_port *port) 272 283 { 273 284 struct mps2_uart_port *mps_port = to_mps2_port(port); ··· 292 275 293 276 mps2_uart_write8(port, control, UARTn_CTRL); 294 277 295 - ret = request_irq(mps_port->rx_irq, mps2_uart_rxirq, 0, 296 - MAKE_NAME(-rx), mps_port); 297 - if (ret) { 298 - dev_err(port->dev, "failed to register rxirq (%d)\n", ret); 299 - return ret; 300 - } 278 + if (mps_port->flags & UART_PORT_COMBINED_IRQ) { 279 + ret = request_irq(port->irq, mps2_uart_combinedirq, 0, 280 + MAKE_NAME(-combined), mps_port); 301 281 302 - ret = request_irq(mps_port->tx_irq, mps2_uart_txirq, 0, 303 - MAKE_NAME(-tx), mps_port); 304 - if (ret) { 305 - dev_err(port->dev, "failed to register txirq (%d)\n", ret); 306 - goto err_free_rxirq; 307 - } 282 + if (ret) { 283 + dev_err(port->dev, "failed to register combinedirq (%d)\n", ret); 284 + return ret; 285 + } 286 + } else { 287 + ret = request_irq(port->irq, mps2_uart_oerrirq, IRQF_SHARED, 288 + MAKE_NAME(-overrun), mps_port); 308 289 309 - ret = request_irq(port->irq, mps2_uart_oerrirq, IRQF_SHARED, 310 - MAKE_NAME(-overrun), mps_port); 290 + if (ret) { 291 + dev_err(port->dev, "failed to register oerrirq (%d)\n", ret); 292 + return ret; 293 + } 311 294 312 - if (ret) { 313 - dev_err(port->dev, "failed to register oerrirq (%d)\n", ret); 314 - goto err_free_txirq; 295 + ret = request_irq(mps_port->rx_irq, mps2_uart_rxirq, 0, 296 + MAKE_NAME(-rx), mps_port); 297 + if (ret) { 298 + dev_err(port->dev, "failed to register rxirq (%d)\n", ret); 299 + goto err_free_oerrirq; 300 + } 301 + 302 + ret = request_irq(mps_port->tx_irq, mps2_uart_txirq, 0, 303 + MAKE_NAME(-tx), mps_port); 304 + if (ret) { 305 + dev_err(port->dev, "failed to register txirq (%d)\n", ret); 306 + goto err_free_rxirq; 307 + } 308 + 315 309 } 316 310 317 311 control |= UARTn_CTRL_RX_GRP | UARTn_CTRL_TX_GRP; ··· 331 303 332 304 return 0; 333 305 334 - err_free_txirq: 335 - free_irq(mps_port->tx_irq, mps_port); 336 306 err_free_rxirq: 337 307 free_irq(mps_port->rx_irq, mps_port); 308 + err_free_oerrirq: 309 + free_irq(port->irq, mps_port); 338 310 339 311 return ret; 340 312 } ··· 348 320 349 321 mps2_uart_write8(port, control, UARTn_CTRL); 350 322 351 - free_irq(mps_port->rx_irq, mps_port); 352 - free_irq(mps_port->tx_irq, mps_port); 323 + if (!mps_port->flags & UART_PORT_COMBINED_IRQ) { 324 + free_irq(mps_port->rx_irq, mps_port); 325 + free_irq(mps_port->tx_irq, mps_port); 326 + } 327 + 353 328 free_irq(port->irq, mps_port); 354 329 } 355 330 ··· 542 511 if (id < 0) 543 512 return id; 544 513 514 + /* Only combined irq is presesnt */ 515 + if (platform_irq_count(pdev) == 1) 516 + mps_port->flags |= UART_PORT_COMBINED_IRQ; 517 + 545 518 mps_port->port.line = id; 546 519 547 520 return 0; ··· 564 529 565 530 mps_port->port.mapbase = res->start; 566 531 mps_port->port.mapsize = resource_size(res); 567 - 568 - mps_port->rx_irq = platform_get_irq(pdev, 0); 569 - mps_port->tx_irq = platform_get_irq(pdev, 1); 570 - mps_port->port.irq = platform_get_irq(pdev, 2); 571 - 572 532 mps_port->port.iotype = UPIO_MEM; 573 533 mps_port->port.flags = UPF_BOOT_AUTOCONF; 574 534 mps_port->port.fifosize = 1; ··· 581 551 mps_port->port.uartclk = clk_get_rate(mps_port->clk); 582 552 583 553 clk_disable_unprepare(mps_port->clk); 554 + 555 + 556 + if (mps_port->flags & UART_PORT_COMBINED_IRQ) { 557 + mps_port->port.irq = platform_get_irq(pdev, 0); 558 + } else { 559 + mps_port->rx_irq = platform_get_irq(pdev, 0); 560 + mps_port->tx_irq = platform_get_irq(pdev, 1); 561 + mps_port->port.irq = platform_get_irq(pdev, 2); 562 + } 584 563 585 564 return ret; 586 565 }