Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  Serial Port driver for Open Firmware platform devices
0004  *
0005  *    Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
0006  */
0007 #include <linux/console.h>
0008 #include <linux/module.h>
0009 #include <linux/slab.h>
0010 #include <linux/serial_core.h>
0011 #include <linux/serial_reg.h>
0012 #include <linux/of_address.h>
0013 #include <linux/of_irq.h>
0014 #include <linux/of_platform.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/clk.h>
0017 #include <linux/reset.h>
0018 
0019 #include "8250.h"
0020 
0021 struct of_serial_info {
0022     struct clk *clk;
0023     struct reset_control *rst;
0024     int type;
0025     int line;
0026 };
0027 
0028 /*
0029  * Fill a struct uart_port for a given device node
0030  */
0031 static int of_platform_serial_setup(struct platform_device *ofdev,
0032             int type, struct uart_8250_port *up,
0033             struct of_serial_info *info)
0034 {
0035     struct resource resource;
0036     struct device_node *np = ofdev->dev.of_node;
0037     struct uart_port *port = &up->port;
0038     u32 clk, spd, prop;
0039     int ret, irq;
0040 
0041     memset(port, 0, sizeof *port);
0042 
0043     pm_runtime_enable(&ofdev->dev);
0044     pm_runtime_get_sync(&ofdev->dev);
0045 
0046     if (of_property_read_u32(np, "clock-frequency", &clk)) {
0047 
0048         /* Get clk rate through clk driver if present */
0049         info->clk = devm_clk_get(&ofdev->dev, NULL);
0050         if (IS_ERR(info->clk)) {
0051             ret = PTR_ERR(info->clk);
0052             if (ret != -EPROBE_DEFER)
0053                 dev_warn(&ofdev->dev,
0054                      "failed to get clock: %d\n", ret);
0055             goto err_pmruntime;
0056         }
0057 
0058         ret = clk_prepare_enable(info->clk);
0059         if (ret < 0)
0060             goto err_pmruntime;
0061 
0062         clk = clk_get_rate(info->clk);
0063     }
0064     /* If current-speed was set, then try not to change it. */
0065     if (of_property_read_u32(np, "current-speed", &spd) == 0)
0066         port->custom_divisor = clk / (16 * spd);
0067 
0068     ret = of_address_to_resource(np, 0, &resource);
0069     if (ret) {
0070         dev_warn(&ofdev->dev, "invalid address\n");
0071         goto err_unprepare;
0072     }
0073 
0074     port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT |
0075                   UPF_FIXED_TYPE;
0076     spin_lock_init(&port->lock);
0077 
0078     if (resource_type(&resource) == IORESOURCE_IO) {
0079         port->iotype = UPIO_PORT;
0080         port->iobase = resource.start;
0081     } else {
0082         port->mapbase = resource.start;
0083         port->mapsize = resource_size(&resource);
0084 
0085         /* Check for shifted address mapping */
0086         if (of_property_read_u32(np, "reg-offset", &prop) == 0) {
0087             if (prop >= port->mapsize) {
0088                 dev_warn(&ofdev->dev, "reg-offset %u exceeds region size %pa\n",
0089                      prop, &port->mapsize);
0090                 ret = -EINVAL;
0091                 goto err_unprepare;
0092             }
0093 
0094             port->mapbase += prop;
0095             port->mapsize -= prop;
0096         }
0097 
0098         port->iotype = UPIO_MEM;
0099         if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
0100             switch (prop) {
0101             case 1:
0102                 port->iotype = UPIO_MEM;
0103                 break;
0104             case 2:
0105                 port->iotype = UPIO_MEM16;
0106                 break;
0107             case 4:
0108                 port->iotype = of_device_is_big_endian(np) ?
0109                            UPIO_MEM32BE : UPIO_MEM32;
0110                 break;
0111             default:
0112                 dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
0113                      prop);
0114                 ret = -EINVAL;
0115                 goto err_unprepare;
0116             }
0117         }
0118         port->flags |= UPF_IOREMAP;
0119     }
0120 
0121     /* Compatibility with the deprecated pxa driver and 8250_pxa drivers. */
0122     if (of_device_is_compatible(np, "mrvl,mmp-uart"))
0123         port->regshift = 2;
0124 
0125     /* Check for registers offset within the devices address range */
0126     if (of_property_read_u32(np, "reg-shift", &prop) == 0)
0127         port->regshift = prop;
0128 
0129     /* Check for fifo size */
0130     if (of_property_read_u32(np, "fifo-size", &prop) == 0)
0131         port->fifosize = prop;
0132 
0133     /* Check for a fixed line number */
0134     ret = of_alias_get_id(np, "serial");
0135     if (ret >= 0)
0136         port->line = ret;
0137 
0138     irq = of_irq_get(np, 0);
0139     if (irq < 0) {
0140         if (irq == -EPROBE_DEFER) {
0141             ret = -EPROBE_DEFER;
0142             goto err_unprepare;
0143         }
0144         /* IRQ support not mandatory */
0145         irq = 0;
0146     }
0147 
0148     port->irq = irq;
0149 
0150     info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL);
0151     if (IS_ERR(info->rst)) {
0152         ret = PTR_ERR(info->rst);
0153         goto err_unprepare;
0154     }
0155 
0156     ret = reset_control_deassert(info->rst);
0157     if (ret)
0158         goto err_unprepare;
0159 
0160     port->type = type;
0161     port->uartclk = clk;
0162 
0163     if (of_property_read_bool(np, "no-loopback-test"))
0164         port->flags |= UPF_SKIP_TEST;
0165 
0166     port->dev = &ofdev->dev;
0167     port->rs485_config = serial8250_em485_config;
0168     port->rs485_supported = serial8250_em485_supported;
0169     up->rs485_start_tx = serial8250_em485_start_tx;
0170     up->rs485_stop_tx = serial8250_em485_stop_tx;
0171 
0172     switch (type) {
0173     case PORT_RT2880:
0174         port->iotype = UPIO_AU;
0175         break;
0176     }
0177 
0178     if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) &&
0179         (of_device_is_compatible(np, "fsl,ns16550") ||
0180          of_device_is_compatible(np, "fsl,16550-FIFO64"))) {
0181         port->handle_irq = fsl8250_handle_irq;
0182         port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
0183     }
0184 
0185     return 0;
0186 err_unprepare:
0187     clk_disable_unprepare(info->clk);
0188 err_pmruntime:
0189     pm_runtime_put_sync(&ofdev->dev);
0190     pm_runtime_disable(&ofdev->dev);
0191     return ret;
0192 }
0193 
0194 /*
0195  * Try to register a serial port
0196  */
0197 static int of_platform_serial_probe(struct platform_device *ofdev)
0198 {
0199     struct of_serial_info *info;
0200     struct uart_8250_port port8250;
0201     unsigned int port_type;
0202     u32 tx_threshold;
0203     int ret;
0204 
0205     if (IS_ENABLED(CONFIG_SERIAL_8250_BCM7271) &&
0206         of_device_is_compatible(ofdev->dev.of_node, "brcm,bcm7271-uart"))
0207         return -ENODEV;
0208 
0209     port_type = (unsigned long)of_device_get_match_data(&ofdev->dev);
0210     if (port_type == PORT_UNKNOWN)
0211         return -EINVAL;
0212 
0213     if (of_property_read_bool(ofdev->dev.of_node, "used-by-rtas"))
0214         return -EBUSY;
0215 
0216     info = kzalloc(sizeof(*info), GFP_KERNEL);
0217     if (info == NULL)
0218         return -ENOMEM;
0219 
0220     memset(&port8250, 0, sizeof(port8250));
0221     ret = of_platform_serial_setup(ofdev, port_type, &port8250, info);
0222     if (ret)
0223         goto err_free;
0224 
0225     if (port8250.port.fifosize)
0226         port8250.capabilities = UART_CAP_FIFO;
0227 
0228     /* Check for TX FIFO threshold & set tx_loadsz */
0229     if ((of_property_read_u32(ofdev->dev.of_node, "tx-threshold",
0230                   &tx_threshold) == 0) &&
0231         (tx_threshold < port8250.port.fifosize))
0232         port8250.tx_loadsz = port8250.port.fifosize - tx_threshold;
0233 
0234     if (of_property_read_bool(ofdev->dev.of_node, "auto-flow-control"))
0235         port8250.capabilities |= UART_CAP_AFE;
0236 
0237     if (of_property_read_u32(ofdev->dev.of_node,
0238             "overrun-throttle-ms",
0239             &port8250.overrun_backoff_time_ms) != 0)
0240         port8250.overrun_backoff_time_ms = 0;
0241 
0242     ret = serial8250_register_8250_port(&port8250);
0243     if (ret < 0)
0244         goto err_dispose;
0245 
0246     info->type = port_type;
0247     info->line = ret;
0248     platform_set_drvdata(ofdev, info);
0249     return 0;
0250 err_dispose:
0251     irq_dispose_mapping(port8250.port.irq);
0252     pm_runtime_put_sync(&ofdev->dev);
0253     pm_runtime_disable(&ofdev->dev);
0254     clk_disable_unprepare(info->clk);
0255 err_free:
0256     kfree(info);
0257     return ret;
0258 }
0259 
0260 /*
0261  * Release a line
0262  */
0263 static int of_platform_serial_remove(struct platform_device *ofdev)
0264 {
0265     struct of_serial_info *info = platform_get_drvdata(ofdev);
0266 
0267     serial8250_unregister_port(info->line);
0268 
0269     reset_control_assert(info->rst);
0270     pm_runtime_put_sync(&ofdev->dev);
0271     pm_runtime_disable(&ofdev->dev);
0272     clk_disable_unprepare(info->clk);
0273     kfree(info);
0274     return 0;
0275 }
0276 
0277 #ifdef CONFIG_PM_SLEEP
0278 static int of_serial_suspend(struct device *dev)
0279 {
0280     struct of_serial_info *info = dev_get_drvdata(dev);
0281     struct uart_8250_port *port8250 = serial8250_get_port(info->line);
0282     struct uart_port *port = &port8250->port;
0283 
0284     serial8250_suspend_port(info->line);
0285 
0286     if (!uart_console(port) || console_suspend_enabled) {
0287         pm_runtime_put_sync(dev);
0288         clk_disable_unprepare(info->clk);
0289     }
0290     return 0;
0291 }
0292 
0293 static int of_serial_resume(struct device *dev)
0294 {
0295     struct of_serial_info *info = dev_get_drvdata(dev);
0296     struct uart_8250_port *port8250 = serial8250_get_port(info->line);
0297     struct uart_port *port = &port8250->port;
0298 
0299     if (!uart_console(port) || console_suspend_enabled) {
0300         pm_runtime_get_sync(dev);
0301         clk_prepare_enable(info->clk);
0302     }
0303 
0304     serial8250_resume_port(info->line);
0305 
0306     return 0;
0307 }
0308 #endif
0309 static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume);
0310 
0311 /*
0312  * A few common types, add more as needed.
0313  */
0314 static const struct of_device_id of_platform_serial_table[] = {
0315     { .compatible = "ns8250",   .data = (void *)PORT_8250, },
0316     { .compatible = "ns16450",  .data = (void *)PORT_16450, },
0317     { .compatible = "ns16550a", .data = (void *)PORT_16550A, },
0318     { .compatible = "ns16550",  .data = (void *)PORT_16550, },
0319     { .compatible = "ns16750",  .data = (void *)PORT_16750, },
0320     { .compatible = "ns16850",  .data = (void *)PORT_16850, },
0321     { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },
0322     { .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, },
0323     { .compatible = "intel,xscale-uart", .data = (void *)PORT_XSCALE, },
0324     { .compatible = "altr,16550-FIFO32",
0325         .data = (void *)PORT_ALTR_16550_F32, },
0326     { .compatible = "altr,16550-FIFO64",
0327         .data = (void *)PORT_ALTR_16550_F64, },
0328     { .compatible = "altr,16550-FIFO128",
0329         .data = (void *)PORT_ALTR_16550_F128, },
0330     { .compatible = "fsl,16550-FIFO64",
0331         .data = (void *)PORT_16550A_FSL64, },
0332     { .compatible = "mediatek,mtk-btif",
0333         .data = (void *)PORT_MTK_BTIF, },
0334     { .compatible = "mrvl,mmp-uart",
0335         .data = (void *)PORT_XSCALE, },
0336     { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
0337     { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, },
0338     { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, },
0339     { /* end of list */ },
0340 };
0341 MODULE_DEVICE_TABLE(of, of_platform_serial_table);
0342 
0343 static struct platform_driver of_platform_serial_driver = {
0344     .driver = {
0345         .name = "of_serial",
0346         .of_match_table = of_platform_serial_table,
0347         .pm = &of_serial_pm_ops,
0348     },
0349     .probe = of_platform_serial_probe,
0350     .remove = of_platform_serial_remove,
0351 };
0352 
0353 module_platform_driver(of_platform_serial_driver);
0354 
0355 MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
0356 MODULE_LICENSE("GPL");
0357 MODULE_DESCRIPTION("Serial Port driver for Open Firmware platform devices");