LCOV - code coverage report
Current view: top level - tty/serial/8250 - 8250_platform.c (source / functions) Coverage Total Hit
Test: TTY Combined Coverage Lines: 0.0 % 180 0
Test Date: 2025-08-26 15:45:50 Functions: 0.0 % 12 0

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0+
       2              : /*
       3              :  *  Universal/legacy platform driver for 8250/16550-type serial ports
       4              :  *
       5              :  *  Supports:
       6              :  *            ISA-compatible 8250/16550 ports
       7              :  *            ACPI 8250/16550 ports
       8              :  *            PNP 8250/16550 ports
       9              :  *            "serial8250" platform devices
      10              :  */
      11              : #include <linux/acpi.h>
      12              : #include <linux/array_size.h>
      13              : #include <linux/io.h>
      14              : #include <linux/module.h>
      15              : #include <linux/moduleparam.h>
      16              : #include <linux/once.h>
      17              : #include <linux/platform_device.h>
      18              : 
      19              : #include <linux/serial_8250.h>
      20              : 
      21              : #ifdef CONFIG_SPARC
      22              : #include <linux/sunserialcore.h>
      23              : #endif
      24              : 
      25              : #include "8250.h"
      26              : 
      27              : /*
      28              :  * Configuration:
      29              :  * share_irqs:     Whether we pass IRQF_SHARED to request_irq().
      30              :  *                 This option is unsafe when used on edge-triggered interrupts.
      31              :  * skip_txen_test: Force skip of txen test at init time.
      32              :  */
      33              : unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
      34              : unsigned int skip_txen_test;
      35              : 
      36              : unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
      37              : 
      38              : #include <asm/serial.h>
      39              : 
      40              : /*
      41              :  * SERIAL_PORT_DFNS tells us about built-in ports that have no
      42              :  * standard enumeration mechanism. Platforms that can find all
      43              :  * serial ports via mechanisms like ACPI or PCI need not supply it.
      44              :  */
      45              : #ifndef SERIAL_PORT_DFNS
      46              : #define SERIAL_PORT_DFNS
      47              : #endif
      48              : 
      49              : static const struct old_serial_port old_serial_port[] = {
      50              :         SERIAL_PORT_DFNS /* defined in asm/serial.h */
      51              : };
      52              : 
      53              : serial8250_isa_config_fn serial8250_isa_config;
      54            0 : void serial8250_set_isa_configurator(serial8250_isa_config_fn v)
      55              : {
      56            0 :         serial8250_isa_config = v;
      57            0 : }
      58              : EXPORT_SYMBOL(serial8250_set_isa_configurator);
      59              : 
      60            0 : static void __init __serial8250_isa_init_ports(void)
      61              : {
      62            0 :         int i, irqflag = 0;
      63              : 
      64            0 :         if (nr_uarts > UART_NR)
      65            0 :                 nr_uarts = UART_NR;
      66              : 
      67              :         /*
      68              :          * Set up initial ISA ports based on nr_uart module param, or else
      69              :          * default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not
      70              :          * need to increase nr_uarts when setting up the initial ISA ports.
      71              :          */
      72            0 :         for (i = 0; i < nr_uarts; i++)
      73            0 :                 serial8250_setup_port(i);
      74              : 
      75              :         /* chain base port ops to support Remote Supervisor Adapter */
      76            0 :         univ8250_port_ops = *univ8250_port_base_ops;
      77            0 :         univ8250_rsa_support(&univ8250_port_ops);
      78              : 
      79            0 :         if (share_irqs)
      80            0 :                 irqflag = IRQF_SHARED;
      81              : 
      82            0 :         for (i = 0; i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; i++) {
      83            0 :                 struct uart_8250_port *up = serial8250_get_port(i);
      84            0 :                 struct uart_port *port = &up->port;
      85              : 
      86            0 :                 port->iobase   = old_serial_port[i].port;
      87            0 :                 port->irq      = irq_canonicalize(old_serial_port[i].irq);
      88            0 :                 port->irqflags = 0;
      89            0 :                 port->uartclk  = old_serial_port[i].baud_base * 16;
      90            0 :                 port->flags    = old_serial_port[i].flags;
      91            0 :                 port->hub6     = 0;
      92            0 :                 port->membase  = old_serial_port[i].iomem_base;
      93            0 :                 port->iotype   = old_serial_port[i].io_type;
      94            0 :                 port->regshift = old_serial_port[i].iomem_reg_shift;
      95              : 
      96            0 :                 port->irqflags |= irqflag;
      97            0 :                 if (serial8250_isa_config != NULL)
      98            0 :                         serial8250_isa_config(i, &up->port, &up->capabilities);
      99            0 :         }
     100            0 : }
     101              : 
     102            0 : void __init serial8250_isa_init_ports(void)
     103              : {
     104            0 :         DO_ONCE(__serial8250_isa_init_ports);
     105            0 : }
     106              : 
     107              : /*
     108              :  * Generic 16550A platform devices
     109              :  */
     110            0 : static int serial8250_probe_acpi(struct platform_device *pdev)
     111              : {
     112            0 :         struct device *dev = &pdev->dev;
     113            0 :         struct uart_8250_port uart = { };
     114            0 :         struct resource *regs;
     115            0 :         int ret, line;
     116              : 
     117            0 :         regs = platform_get_mem_or_io(pdev, 0);
     118            0 :         if (!regs)
     119            0 :                 return dev_err_probe(dev, -EINVAL, "no registers defined\n");
     120              : 
     121            0 :         switch (resource_type(regs)) {
     122              :         case IORESOURCE_IO:
     123            0 :                 uart.port.iobase = regs->start;
     124            0 :                 break;
     125              :         case IORESOURCE_MEM:
     126            0 :                 uart.port.mapbase = regs->start;
     127            0 :                 uart.port.mapsize = resource_size(regs);
     128            0 :                 uart.port.flags = UPF_IOREMAP;
     129            0 :                 break;
     130              :         default:
     131            0 :                 return -EINVAL;
     132              :         }
     133              : 
     134              :         /* default clock frequency */
     135            0 :         uart.port.uartclk = 1843200;
     136            0 :         uart.port.type = PORT_16550A;
     137            0 :         uart.port.dev = &pdev->dev;
     138            0 :         uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
     139              : 
     140            0 :         ret = uart_read_and_validate_port_properties(&uart.port);
     141              :         /* no interrupt -> fall back to polling */
     142            0 :         if (ret == -ENXIO)
     143            0 :                 ret = 0;
     144            0 :         if (ret)
     145            0 :                 return ret;
     146              : 
     147            0 :         line = serial8250_register_8250_port(&uart);
     148            0 :         if (line < 0)
     149            0 :                 return line;
     150              : 
     151            0 :         return 0;
     152            0 : }
     153              : 
     154            0 : static int serial8250_probe_platform(struct platform_device *dev, struct plat_serial8250_port *p)
     155              : {
     156            0 :         struct uart_8250_port uart;
     157            0 :         int ret, i, irqflag = 0;
     158              : 
     159            0 :         memset(&uart, 0, sizeof(uart));
     160              : 
     161            0 :         if (share_irqs)
     162            0 :                 irqflag = IRQF_SHARED;
     163              : 
     164            0 :         for (i = 0; p && p->flags != 0; p++, i++) {
     165            0 :                 uart.port.iobase        = p->iobase;
     166            0 :                 uart.port.membase       = p->membase;
     167            0 :                 uart.port.irq           = p->irq;
     168            0 :                 uart.port.irqflags      = p->irqflags;
     169            0 :                 uart.port.uartclk       = p->uartclk;
     170            0 :                 uart.port.regshift      = p->regshift;
     171            0 :                 uart.port.iotype        = p->iotype;
     172            0 :                 uart.port.flags         = p->flags;
     173            0 :                 uart.port.mapbase       = p->mapbase;
     174            0 :                 uart.port.mapsize       = p->mapsize;
     175            0 :                 uart.port.hub6          = p->hub6;
     176            0 :                 uart.port.has_sysrq     = p->has_sysrq;
     177            0 :                 uart.port.private_data  = p->private_data;
     178            0 :                 uart.port.type          = p->type;
     179            0 :                 uart.bugs               = p->bugs;
     180            0 :                 uart.port.serial_in     = p->serial_in;
     181            0 :                 uart.port.serial_out    = p->serial_out;
     182            0 :                 uart.dl_read            = p->dl_read;
     183            0 :                 uart.dl_write           = p->dl_write;
     184            0 :                 uart.port.handle_irq    = p->handle_irq;
     185            0 :                 uart.port.handle_break  = p->handle_break;
     186            0 :                 uart.port.set_termios   = p->set_termios;
     187            0 :                 uart.port.set_ldisc     = p->set_ldisc;
     188            0 :                 uart.port.get_mctrl     = p->get_mctrl;
     189            0 :                 uart.port.pm            = p->pm;
     190            0 :                 uart.port.dev           = &dev->dev;
     191            0 :                 uart.port.irqflags      |= irqflag;
     192            0 :                 ret = serial8250_register_8250_port(&uart);
     193            0 :                 if (ret < 0) {
     194            0 :                         dev_err(&dev->dev, "unable to register port at index %d "
     195              :                                 "(IO%lx MEM%llx IRQ%d): %d\n", i,
     196              :                                 p->iobase, (unsigned long long)p->mapbase,
     197              :                                 p->irq, ret);
     198            0 :                 }
     199            0 :         }
     200            0 :         return 0;
     201            0 : }
     202              : 
     203              : /*
     204              :  * Register a set of serial devices attached to a platform device.
     205              :  * The list is terminated with a zero flags entry, which means we expect
     206              :  * all entries to have at least UPF_BOOT_AUTOCONF set.
     207              :  */
     208            0 : static int serial8250_probe(struct platform_device *pdev)
     209              : {
     210            0 :         struct device *dev = &pdev->dev;
     211            0 :         struct plat_serial8250_port *p;
     212              : 
     213            0 :         p = dev_get_platdata(dev);
     214            0 :         if (p)
     215            0 :                 return serial8250_probe_platform(pdev, p);
     216              : 
     217              :         /*
     218              :          * Probe platform UART devices defined using standard hardware
     219              :          * discovery mechanism like ACPI or DT. Support only ACPI based
     220              :          * serial device for now.
     221              :          */
     222            0 :         if (has_acpi_companion(dev))
     223            0 :                 return serial8250_probe_acpi(pdev);
     224              : 
     225            0 :         return 0;
     226            0 : }
     227              : 
     228              : /*
     229              :  * Remove serial ports registered against a platform device.
     230              :  */
     231            0 : static void serial8250_remove(struct platform_device *dev)
     232              : {
     233            0 :         int i;
     234              : 
     235            0 :         for (i = 0; i < nr_uarts; i++) {
     236            0 :                 struct uart_8250_port *up = serial8250_get_port(i);
     237              : 
     238            0 :                 if (up->port.dev == &dev->dev)
     239            0 :                         serial8250_unregister_port(i);
     240            0 :         }
     241            0 : }
     242              : 
     243            0 : static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
     244              : {
     245            0 :         int i;
     246              : 
     247            0 :         for (i = 0; i < UART_NR; i++) {
     248            0 :                 struct uart_8250_port *up = serial8250_get_port(i);
     249              : 
     250            0 :                 if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
     251            0 :                         uart_suspend_port(&serial8250_reg, &up->port);
     252            0 :         }
     253              : 
     254            0 :         return 0;
     255            0 : }
     256              : 
     257            0 : static int serial8250_resume(struct platform_device *dev)
     258              : {
     259            0 :         int i;
     260              : 
     261            0 :         for (i = 0; i < UART_NR; i++) {
     262            0 :                 struct uart_8250_port *up = serial8250_get_port(i);
     263              : 
     264            0 :                 if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
     265            0 :                         serial8250_resume_port(i);
     266            0 :         }
     267              : 
     268            0 :         return 0;
     269            0 : }
     270              : 
     271              : static const struct acpi_device_id acpi_platform_serial_table[] = {
     272              :         { "RSCV0003" }, /* RISC-V Generic 16550A UART */
     273              :         { }
     274              : };
     275              : MODULE_DEVICE_TABLE(acpi, acpi_platform_serial_table);
     276              : 
     277              : static struct platform_driver serial8250_isa_driver = {
     278              :         .probe          = serial8250_probe,
     279              :         .remove         = serial8250_remove,
     280              :         .suspend        = serial8250_suspend,
     281              :         .resume         = serial8250_resume,
     282              :         .driver         = {
     283              :                 .name   = "serial8250",
     284              :                 .acpi_match_table = acpi_platform_serial_table,
     285              :         },
     286              : };
     287              : 
     288              : /*
     289              :  * This "device" covers _all_ ISA 8250-compatible serial devices listed
     290              :  * in the table in include/asm/serial.h.
     291              :  */
     292              : struct platform_device *serial8250_isa_devs;
     293              : 
     294            0 : static int __init serial8250_init(void)
     295              : {
     296            0 :         int ret;
     297              : 
     298            0 :         if (nr_uarts == 0)
     299            0 :                 return -ENODEV;
     300              : 
     301            0 :         serial8250_isa_init_ports();
     302              : 
     303            0 :         pr_info("Serial: 8250/16550 driver, %d ports, IRQ sharing %s\n",
     304              :                 nr_uarts, str_enabled_disabled(share_irqs));
     305              : 
     306              : #ifdef CONFIG_SPARC
     307              :         ret = sunserial_register_minors(&serial8250_reg, UART_NR);
     308              : #else
     309            0 :         serial8250_reg.nr = UART_NR;
     310            0 :         ret = uart_register_driver(&serial8250_reg);
     311              : #endif
     312            0 :         if (ret)
     313            0 :                 goto out;
     314              : 
     315            0 :         ret = serial8250_pnp_init();
     316            0 :         if (ret)
     317            0 :                 goto unreg_uart_drv;
     318              : 
     319            0 :         serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY);
     320            0 :         if (!serial8250_isa_devs) {
     321            0 :                 ret = -ENOMEM;
     322            0 :                 goto unreg_pnp;
     323              :         }
     324              : 
     325            0 :         ret = platform_device_add(serial8250_isa_devs);
     326            0 :         if (ret)
     327            0 :                 goto put_dev;
     328              : 
     329            0 :         serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
     330              : 
     331            0 :         ret = platform_driver_register(&serial8250_isa_driver);
     332            0 :         if (ret == 0)
     333            0 :                 goto out;
     334              : 
     335            0 :         platform_device_del(serial8250_isa_devs);
     336              : put_dev:
     337            0 :         platform_device_put(serial8250_isa_devs);
     338              : unreg_pnp:
     339            0 :         serial8250_pnp_exit();
     340              : unreg_uart_drv:
     341              : #ifdef CONFIG_SPARC
     342              :         sunserial_unregister_minors(&serial8250_reg, UART_NR);
     343              : #else
     344            0 :         uart_unregister_driver(&serial8250_reg);
     345              : #endif
     346              : out:
     347            0 :         return ret;
     348            0 : }
     349              : module_init(serial8250_init);
     350              : 
     351            0 : static void __exit serial8250_exit(void)
     352              : {
     353            0 :         struct platform_device *isa_dev = serial8250_isa_devs;
     354              : 
     355              :         /*
     356              :          * This tells serial8250_unregister_port() not to re-register
     357              :          * the ports (thereby making serial8250_isa_driver permanently
     358              :          * in use).
     359              :          */
     360            0 :         serial8250_isa_devs = NULL;
     361              : 
     362            0 :         platform_driver_unregister(&serial8250_isa_driver);
     363            0 :         platform_device_unregister(isa_dev);
     364              : 
     365            0 :         serial8250_pnp_exit();
     366              : 
     367              : #ifdef CONFIG_SPARC
     368              :         sunserial_unregister_minors(&serial8250_reg, UART_NR);
     369              : #else
     370            0 :         uart_unregister_driver(&serial8250_reg);
     371              : #endif
     372            0 : }
     373              : module_exit(serial8250_exit);
     374              : 
     375              : MODULE_LICENSE("GPL");
     376              : MODULE_DESCRIPTION("Generic 8250/16x50 serial platform driver");
     377              : 
     378              : module_param_hw(share_irqs, uint, other, 0644);
     379              : MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices (unsafe)");
     380              : 
     381              : module_param(nr_uarts, uint, 0644);
     382              : MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
     383              : 
     384              : module_param(skip_txen_test, uint, 0644);
     385              : MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
     386              : 
     387              : MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
     388              : 
     389              : #ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS
     390              : #ifndef MODULE
     391              : /*
     392              :  * This module was renamed to 8250_core in 3.7. Keep the old "8250" name
     393              :  * working as well for the module options so we don't break people. We
     394              :  * need to keep the names identical and the convenient macros will happily
     395              :  * refuse to let us do that by failing the build with redefinition errors
     396              :  * of global variables. So we stick them inside a dummy function to avoid
     397              :  * those conflicts. The options still get parsed, and the redefined
     398              :  * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
     399              :  *
     400              :  * This is hacky.  I'm sorry.
     401              :  */
     402            0 : static void __used s8250_options(void)
     403              : {
     404              : #undef MODULE_PARAM_PREFIX
     405              : #define MODULE_PARAM_PREFIX "8250_core."
     406              : 
     407              :         module_param_cb(share_irqs, &param_ops_uint, &share_irqs, 0644);
     408              :         module_param_cb(nr_uarts, &param_ops_uint, &nr_uarts, 0644);
     409              :         module_param_cb(skip_txen_test, &param_ops_uint, &skip_txen_test, 0644);
     410            0 : }
     411              : #else
     412              : MODULE_ALIAS("8250_core");
     413              : #endif
     414              : #endif
        

Generated by: LCOV version 2.0-1