brintos

brintos / linux-shallow public Read only

0
0
Text · 8.1 KiB · d35f1d2 Raw
320 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Serial core port device driver4 *5 * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/6 * Author: Tony Lindgren <tony@atomide.com>7 */8 9#include <linux/device.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/platform_device.h>13#include <linux/pm_runtime.h>14#include <linux/pnp.h>15#include <linux/property.h>16#include <linux/serial_core.h>17#include <linux/spinlock.h>18 19#include "serial_base.h"20 21#define SERIAL_PORT_AUTOSUSPEND_DELAY_MS	50022 23/* Only considers pending TX for now. Caller must take care of locking */24static int __serial_port_busy(struct uart_port *port)25{26	return !uart_tx_stopped(port) &&27		!kfifo_is_empty(&port->state->port.xmit_fifo);28}29 30static int serial_port_runtime_resume(struct device *dev)31{32	struct serial_port_device *port_dev = to_serial_base_port_device(dev);33	struct uart_port *port;34	unsigned long flags;35 36	port = port_dev->port;37 38	if (port->flags & UPF_DEAD)39		goto out;40 41	/* Flush any pending TX for the port */42	uart_port_lock_irqsave(port, &flags);43	if (!port_dev->tx_enabled)44		goto unlock;45	if (__serial_port_busy(port))46		port->ops->start_tx(port);47 48unlock:49	uart_port_unlock_irqrestore(port, flags);50 51out:52	pm_runtime_mark_last_busy(dev);53 54	return 0;55}56 57static int serial_port_runtime_suspend(struct device *dev)58{59	struct serial_port_device *port_dev = to_serial_base_port_device(dev);60	struct uart_port *port = port_dev->port;61	unsigned long flags;62	bool busy;63 64	if (port->flags & UPF_DEAD)65		return 0;66 67	/*68	 * Nothing to do on pm_runtime_force_suspend(), see69	 * DEFINE_RUNTIME_DEV_PM_OPS.70	 */71	if (!pm_runtime_enabled(dev))72		return 0;73 74	uart_port_lock_irqsave(port, &flags);75	if (!port_dev->tx_enabled) {76		uart_port_unlock_irqrestore(port, flags);77		return 0;78	}79 80	busy = __serial_port_busy(port);81	if (busy)82		port->ops->start_tx(port);83	uart_port_unlock_irqrestore(port, flags);84 85	if (busy)86		pm_runtime_mark_last_busy(dev);87 88	return busy ? -EBUSY : 0;89}90 91static void serial_base_port_set_tx(struct uart_port *port,92				    struct serial_port_device *port_dev,93				    bool enabled)94{95	unsigned long flags;96 97	uart_port_lock_irqsave(port, &flags);98	port_dev->tx_enabled = enabled;99	uart_port_unlock_irqrestore(port, flags);100}101 102void serial_base_port_startup(struct uart_port *port)103{104	struct serial_port_device *port_dev = port->port_dev;105 106	serial_base_port_set_tx(port, port_dev, true);107}108 109void serial_base_port_shutdown(struct uart_port *port)110{111	struct serial_port_device *port_dev = port->port_dev;112 113	serial_base_port_set_tx(port, port_dev, false);114}115 116static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm,117				 serial_port_runtime_suspend,118				 serial_port_runtime_resume, NULL);119 120static int serial_port_probe(struct device *dev)121{122	pm_runtime_enable(dev);123	pm_runtime_set_autosuspend_delay(dev, SERIAL_PORT_AUTOSUSPEND_DELAY_MS);124	pm_runtime_use_autosuspend(dev);125 126	return 0;127}128 129static int serial_port_remove(struct device *dev)130{131	pm_runtime_dont_use_autosuspend(dev);132	pm_runtime_disable(dev);133 134	return 0;135}136 137/*138 * Serial core port device init functions. Note that the physical serial139 * port device driver may not have completed probe at this point.140 */141int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)142{143	return serial_ctrl_register_port(drv, port);144}145EXPORT_SYMBOL(uart_add_one_port);146 147void uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)148{149	serial_ctrl_unregister_port(drv, port);150}151EXPORT_SYMBOL(uart_remove_one_port);152 153/**154 * __uart_read_properties - read firmware properties of the given UART port155 * @port: corresponding port156 * @use_defaults: apply defaults (when %true) or validate the values (when %false)157 *158 * The following device properties are supported:159 *   - clock-frequency (optional)160 *   - fifo-size (optional)161 *   - no-loopback-test (optional)162 *   - reg-shift (defaults may apply)163 *   - reg-offset (value may be validated)164 *   - reg-io-width (defaults may apply or value may be validated)165 *   - interrupts (OF only)166 *   - serial [alias ID] (OF only)167 *168 * If the port->dev is of struct platform_device type the interrupt line169 * will be retrieved via platform_get_irq() call against that device.170 * Otherwise it will be assigned by fwnode_irq_get() call. In both cases171 * the index 0 of the resource is used.172 *173 * The caller is responsible to initialize the following fields of the @port174 *   ->dev (must be valid)175 *   ->flags176 *   ->mapbase177 *   ->mapsize178 *   ->regshift (if @use_defaults is false)179 * before calling this function. Alternatively the above mentioned fields180 * may be zeroed, in such case the only ones, that have associated properties181 * found, will be set to the respective values.182 *183 * If no error happened, the ->irq, ->mapbase, ->mapsize will be altered.184 * The ->iotype is always altered.185 *186 * When @use_defaults is true and the respective property is not found187 * the following values will be applied:188 *   ->regshift = 0189 * In this case IRQ must be provided, otherwise an error will be returned.190 *191 * When @use_defaults is false and the respective property is found192 * the following values will be validated:193 *   - reg-io-width (->iotype)194 *   - reg-offset (->mapsize against ->mapbase)195 *196 * Returns: 0 on success or negative errno on failure197 */198static int __uart_read_properties(struct uart_port *port, bool use_defaults)199{200	struct device *dev = port->dev;201	u32 value;202	int ret;203 204	/* Read optional UART functional clock frequency */205	device_property_read_u32(dev, "clock-frequency", &port->uartclk);206 207	/* Read the registers alignment (default: 8-bit) */208	ret = device_property_read_u32(dev, "reg-shift", &value);209	if (ret)210		port->regshift = use_defaults ? 0 : port->regshift;211	else212		port->regshift = value;213 214	/* Read the registers I/O access type (default: MMIO 8-bit) */215	ret = device_property_read_u32(dev, "reg-io-width", &value);216	if (ret) {217		port->iotype = UPIO_MEM;218	} else {219		switch (value) {220		case 1:221			port->iotype = UPIO_MEM;222			break;223		case 2:224			port->iotype = UPIO_MEM16;225			break;226		case 4:227			port->iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32;228			break;229		default:230			if (!use_defaults) {231				dev_err(dev, "Unsupported reg-io-width (%u)\n", value);232				return -EINVAL;233			}234			port->iotype = UPIO_UNKNOWN;235			break;236		}237	}238 239	/* Read the address mapping base offset (default: no offset) */240	ret = device_property_read_u32(dev, "reg-offset", &value);241	if (ret)242		value = 0;243 244	/* Check for shifted address mapping overflow */245	if (!use_defaults && port->mapsize < value) {246		dev_err(dev, "reg-offset %u exceeds region size %pa\n", value, &port->mapsize);247		return -EINVAL;248	}249 250	port->mapbase += value;251	port->mapsize -= value;252 253	/* Read optional FIFO size */254	device_property_read_u32(dev, "fifo-size", &port->fifosize);255 256	if (device_property_read_bool(dev, "no-loopback-test"))257		port->flags |= UPF_SKIP_TEST;258 259	/* Get index of serial line, if found in DT aliases */260	ret = of_alias_get_id(dev_of_node(dev), "serial");261	if (ret >= 0)262		port->line = ret;263 264	if (dev_is_platform(dev))265		ret = platform_get_irq(to_platform_device(dev), 0);266	else if (dev_is_pnp(dev)) {267		ret = pnp_irq(to_pnp_dev(dev), 0);268		if (ret < 0)269			ret = -ENXIO;270	} else271		ret = fwnode_irq_get(dev_fwnode(dev), 0);272	if (ret == -EPROBE_DEFER)273		return ret;274	if (ret > 0)275		port->irq = ret;276	else if (use_defaults)277		/* By default IRQ support is mandatory */278		return ret;279	else280		port->irq = 0;281 282	port->flags |= UPF_SHARE_IRQ;283 284	return 0;285}286 287int uart_read_port_properties(struct uart_port *port)288{289	return __uart_read_properties(port, true);290}291EXPORT_SYMBOL_GPL(uart_read_port_properties);292 293int uart_read_and_validate_port_properties(struct uart_port *port)294{295	return __uart_read_properties(port, false);296}297EXPORT_SYMBOL_GPL(uart_read_and_validate_port_properties);298 299static struct device_driver serial_port_driver = {300	.name = "port",301	.suppress_bind_attrs = true,302	.probe = serial_port_probe,303	.remove = serial_port_remove,304	.pm = pm_ptr(&serial_port_pm),305};306 307int serial_base_port_init(void)308{309	return serial_base_driver_register(&serial_port_driver);310}311 312void serial_base_port_exit(void)313{314	serial_base_driver_unregister(&serial_port_driver);315}316 317MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");318MODULE_DESCRIPTION("Serial controller port driver");319MODULE_LICENSE("GPL");320