File Index
Files and directories
Sign in
FILE

8250_ni.c

File preview with syntax highlighting.

linux-6.19.14/drivers/tty/serial/8250/8250_ni.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * NI 16550 UART Driver
  4 *
  5 * The National Instruments (NI) 16550 is a UART that is compatible with the
  6 * TL16C550C and OX16C950B register interfaces, but has additional functions
  7 * for RS-485 transceiver control. This driver implements support for the
  8 * additional functionality on top of the standard serial8250 core.
  9 *
 10 * Copyright 2012-2023 National Instruments Corporation
 11 */
 12
 13#include <linux/bitfield.h>
 14#include <linux/bits.h>
 15#include <linux/clk.h>
 16#include <linux/device.h>
 17#include <linux/io.h>
 18#include <linux/init.h>
 19#include <linux/mod_devicetable.h>
 20#include <linux/module.h>
 21#include <linux/platform_device.h>
 22#include <linux/property.h>
 23#include <linux/serial_core.h>
 24#include <linux/types.h>
 25
 26#include "8250.h"
 27
 28/* Extra bits in UART_ACR */
 29#define NI16550_ACR_AUTO_DTR_EN			BIT(4)
 30
 31/* TFS - TX FIFO Size */
 32#define NI16550_TFS_OFFSET	0x0C
 33/* RFS - RX FIFO Size */
 34#define NI16550_RFS_OFFSET	0x0D
 35
 36/* PMR - Port Mode Register */
 37#define NI16550_PMR_OFFSET	0x0E
 38/* PMR[1:0] - Port Capabilities */
 39#define NI16550_PMR_CAP_MASK		GENMASK(1, 0)
 40#define NI16550_PMR_NOT_IMPL		FIELD_PREP(NI16550_PMR_CAP_MASK, 0) /* not implemented */
 41#define NI16550_PMR_CAP_RS232		FIELD_PREP(NI16550_PMR_CAP_MASK, 1) /* RS-232 capable */
 42#define NI16550_PMR_CAP_RS485		FIELD_PREP(NI16550_PMR_CAP_MASK, 2) /* RS-485 capable */
 43#define NI16550_PMR_CAP_DUAL		FIELD_PREP(NI16550_PMR_CAP_MASK, 3) /* dual-port */
 44/* PMR[4] - Interface Mode */
 45#define NI16550_PMR_MODE_MASK		GENMASK(4, 4)
 46#define NI16550_PMR_MODE_RS232		FIELD_PREP(NI16550_PMR_MODE_MASK, 0) /* currently 232 */
 47#define NI16550_PMR_MODE_RS485		FIELD_PREP(NI16550_PMR_MODE_MASK, 1) /* currently 485 */
 48
 49/* PCR - Port Control Register */
 50/*
 51 * Wire Mode      | Tx enabled?          | Rx enabled?
 52 * ---------------|----------------------|--------------------------
 53 * PCR_RS422      | Always               | Always
 54 * PCR_ECHO_RS485 | When DTR asserted    | Always
 55 * PCR_DTR_RS485  | When DTR asserted    | Disabled when TX enabled
 56 * PCR_AUTO_RS485 | When data in TX FIFO | Disabled when TX enabled
 57 */
 58#define NI16550_PCR_OFFSET	0x0F
 59#define NI16550_PCR_WIRE_MODE_MASK		GENMASK(1, 0)
 60#define NI16550_PCR_RS422			FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 0)
 61#define NI16550_PCR_ECHO_RS485			FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 1)
 62#define NI16550_PCR_DTR_RS485			FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 2)
 63#define NI16550_PCR_AUTO_RS485			FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 3)
 64#define NI16550_PCR_TXVR_ENABLE_BIT		BIT(3)
 65#define NI16550_PCR_RS485_TERMINATION_BIT	BIT(6)
 66
 67/* flags for ni16550_device_info */
 68#define NI_HAS_PMR		BIT(0)
 69
 70struct ni16550_device_info {
 71	u32 uartclk;
 72	u8 prescaler;
 73	u8 flags;
 74};
 75
 76struct ni16550_data {
 77	int line;
 78	struct clk *clk;
 79};
 80
 81static int ni16550_enable_transceivers(struct uart_port *port)
 82{
 83	u8 pcr;
 84
 85	pcr = port->serial_in(port, NI16550_PCR_OFFSET);
 86	pcr |= NI16550_PCR_TXVR_ENABLE_BIT;
 87	dev_dbg(port->dev, "enable transceivers: write pcr: 0x%02x\n", pcr);
 88	port->serial_out(port, NI16550_PCR_OFFSET, pcr);
 89
 90	return 0;
 91}
 92
 93static int ni16550_disable_transceivers(struct uart_port *port)
 94{
 95	u8 pcr;
 96
 97	pcr = serial_port_in(port, NI16550_PCR_OFFSET);
 98	pcr &= ~NI16550_PCR_TXVR_ENABLE_BIT;
 99	dev_dbg(port->dev, "disable transceivers: write pcr: 0x%02x\n", pcr);
100	serial_port_out(port, NI16550_PCR_OFFSET, pcr);
101
102	return 0;
103}
104
105static int ni16550_rs485_config(struct uart_port *port,
106				struct ktermios *termios,
107				struct serial_rs485 *rs485)
108{
109	struct uart_8250_port *up = container_of(port, struct uart_8250_port, port);
110	u8 pcr;
111
112	pcr = serial_port_in(port, NI16550_PCR_OFFSET);
113	pcr &= ~NI16550_PCR_WIRE_MODE_MASK;
114
115	if ((rs485->flags & SER_RS485_MODE_RS422) ||
116	    !(rs485->flags & SER_RS485_ENABLED)) {
117		/* RS-422 */
118		pcr |= NI16550_PCR_RS422;
119		up->acr &= ~NI16550_ACR_AUTO_DTR_EN;
120	} else {
121		/* RS-485 2-wire Auto */
122		pcr |= NI16550_PCR_AUTO_RS485;
123		up->acr |= NI16550_ACR_AUTO_DTR_EN;
124	}
125
126	dev_dbg(port->dev, "config rs485: write pcr: 0x%02x, acr: %02x\n", pcr, up->acr);
127	serial_port_out(port, NI16550_PCR_OFFSET, pcr);
128	serial_icr_write(up, UART_ACR, up->acr);
129
130	return 0;
131}
132
133static bool is_pmr_rs232_mode(struct uart_8250_port *up)
134{
135	u8 pmr = serial_in(up, NI16550_PMR_OFFSET);
136	u8 pmr_mode = pmr & NI16550_PMR_MODE_MASK;
137	u8 pmr_cap = pmr & NI16550_PMR_CAP_MASK;
138
139	/*
140	 * If the PMR is not implemented, then by default NI UARTs are
141	 * connected to RS-485 transceivers
142	 */
143	if (pmr_cap == NI16550_PMR_NOT_IMPL)
144		return false;
145
146	if (pmr_cap == NI16550_PMR_CAP_DUAL)
147		/*
148		 * If the port is dual-mode capable, then read the mode bit
149		 * to know the current mode
150		 */
151		return pmr_mode == NI16550_PMR_MODE_RS232;
152	/*
153	 * If it is not dual-mode capable, then decide based on the
154	 * capability
155	 */
156	return pmr_cap == NI16550_PMR_CAP_RS232;
157}
158
159static void ni16550_config_prescaler(struct uart_8250_port *up,
160				     u8 prescaler)
161{
162	/*
163	 * Page in the Enhanced Mode Registers
164	 * Sets EFR[4] for Enhanced Mode.
165	 */
166	u8 lcr_value;
167	u8 efr_value;
168
169	lcr_value = serial_in(up, UART_LCR);
170	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
171
172	efr_value = serial_in(up, UART_EFR);
173	efr_value |= UART_EFR_ECB;
174
175	serial_out(up, UART_EFR, efr_value);
176
177	/* Page out the Enhanced Mode Registers */
178	serial_out(up, UART_LCR, lcr_value);
179
180	/* Set prescaler to CPR register. */
181	serial_out(up, UART_SCR, UART_CPR);
182	serial_out(up, UART_ICR, prescaler);
183}
184
185static const struct serial_rs485 ni16550_rs485_supported = {
186	.flags = SER_RS485_ENABLED | SER_RS485_MODE_RS422 | SER_RS485_RTS_ON_SEND |
187		 SER_RS485_RTS_AFTER_SEND,
188	/*
189	 * delay_rts_* and RX_DURING_TX are not supported.
190	 *
191	 * RTS_{ON,AFTER}_SEND are supported, but ignored; the transceiver
192	 * is connected in only one way and we don't need userspace to tell
193	 * us, but want to retain compatibility with applications that do.
194	 */
195};
196
197static void ni16550_rs485_setup(struct uart_port *port)
198{
199	port->rs485_config = ni16550_rs485_config;
200	port->rs485_supported = ni16550_rs485_supported;
201	/*
202	 * The hardware comes up by default in 2-wire auto mode and we
203	 * set the flags to represent that
204	 */
205	port->rs485.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
206}
207
208static int ni16550_port_startup(struct uart_port *port)
209{
210	int ret;
211
212	ret = serial8250_do_startup(port);
213	if (ret)
214		return ret;
215
216	return ni16550_enable_transceivers(port);
217}
218
219static void ni16550_port_shutdown(struct uart_port *port)
220{
221	ni16550_disable_transceivers(port);
222
223	serial8250_do_shutdown(port);
224}
225
226static int ni16550_get_regs(struct platform_device *pdev,
227			    struct uart_port *port)
228{
229	struct resource *regs;
230
231	regs = platform_get_mem_or_io(pdev, 0);
232	if (!regs)
233		return dev_err_probe(&pdev->dev, -EINVAL, "no registers defined\n");
234
235	switch (resource_type(regs)) {
236	case IORESOURCE_IO:
237		port->iotype = UPIO_PORT;
238		port->iobase = regs->start;
239
240		return 0;
241	case IORESOURCE_MEM:
242		port->iotype = UPIO_MEM;
243		port->mapbase = regs->start;
244		port->mapsize = resource_size(regs);
245		port->flags |= UPF_IOREMAP;
246
247		return 0;
248	default:
249		return -EINVAL;
250	}
251}
252
253/*
254 * Very old implementations don't have the TFS or RFS registers
255 * defined, so we may read all-0s or all-1s. For such devices,
256 * assume a FIFO size of 128.
257 */
258static u8 ni16550_read_fifo_size(struct uart_8250_port *uart, int reg)
259{
260	u8 value = serial_in(uart, reg);
261
262	if (value == 0x00 || value == 0xFF)
263		return 128;
264
265	return value;
266}
267
268static void ni16550_set_mctrl(struct uart_port *port, unsigned int mctrl)
269{
270	struct uart_8250_port *up = up_to_u8250p(port);
271
272	up->mcr |= UART_MCR_CLKSEL;
273	serial8250_do_set_mctrl(port, mctrl);
274}
275
276static int ni16550_probe(struct platform_device *pdev)
277{
278	struct uart_8250_port *uart __free(kfree) = NULL;
279	const struct ni16550_device_info *info;
280	struct device *dev = &pdev->dev;
281	unsigned int txfifosz, rxfifosz;
282	struct ni16550_data *data;
283	unsigned int prescaler;
284	const char *portmode;
285	bool rs232_property;
286	int ret;
287
288	uart = kzalloc(sizeof(*uart), GFP_KERNEL);
289	if (!uart)
290		return -ENOMEM;
291
292	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
293	if (!data)
294		return -ENOMEM;
295
296	spin_lock_init(&uart->port.lock);
297
298	ret = ni16550_get_regs(pdev, &uart->port);
299	if (ret < 0)
300		return ret;
301
302	/* early setup so that serial_in()/serial_out() work */
303	serial8250_set_defaults(uart);
304
305	info = device_get_match_data(dev);
306
307	uart->port.dev		= dev;
308	uart->port.flags	= UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE;
309	uart->port.startup	= ni16550_port_startup;
310	uart->port.shutdown	= ni16550_port_shutdown;
311
312	/*
313	 * Hardware instantiation of FIFO sizes are held in registers.
314	 */
315	txfifosz = ni16550_read_fifo_size(uart, NI16550_TFS_OFFSET);
316	rxfifosz = ni16550_read_fifo_size(uart, NI16550_RFS_OFFSET);
317
318	dev_dbg(dev, "NI 16550 has TX FIFO size %u, RX FIFO size %u\n",
319		txfifosz, rxfifosz);
320
321	uart->port.type		= PORT_16550A;
322	uart->port.fifosize	= txfifosz;
323	uart->tx_loadsz		= txfifosz;
324	uart->fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
325	uart->capabilities	= UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR;
326
327	/*
328	 * Declaration of the base clock frequency can come from one of:
329	 * - static declaration in this driver (for older ACPI IDs)
330	 * - a "clock-frequency" ACPI
331	 */
332	uart->port.uartclk = info->uartclk;
333
334	ret = uart_read_port_properties(&uart->port);
335	if (ret)
336		return ret;
337
338	if (!uart->port.uartclk) {
339		data->clk = devm_clk_get_enabled(dev, NULL);
340		if (!IS_ERR(data->clk))
341			uart->port.uartclk = clk_get_rate(data->clk);
342	}
343
344	if (!uart->port.uartclk)
345		return dev_err_probe(dev, -ENODEV, "unable to determine clock frequency!\n");
346
347	prescaler = info->prescaler;
348	device_property_read_u32(dev, "clock-prescaler", &prescaler);
349	if (prescaler) {
350		uart->port.set_mctrl = ni16550_set_mctrl;
351		ni16550_config_prescaler(uart, (u8)prescaler);
352	}
353
354	/*
355	 * The determination of whether or not this is an RS-485 or RS-232 port
356	 * can come from the PMR (if present), otherwise we're solely an RS-485
357	 * port.
358	 *
359	 * This is a device-specific property, and there are old devices in the
360	 * field using "transceiver" as an ACPI property, so we have to check
361	 * for that as well.
362	 */
363	if (!device_property_read_string(dev, "transceiver", &portmode)) {
364		rs232_property = strncmp(portmode, "RS-232", 6) == 0;
365
366		dev_dbg(dev, "port is in %s mode (via device property)\n",
367			rs232_property ? "RS-232" : "RS-485");
368	} else if (info->flags & NI_HAS_PMR) {
369		rs232_property = is_pmr_rs232_mode(uart);
370
371		dev_dbg(dev, "port is in %s mode (via PMR)\n",
372			rs232_property ? "RS-232" : "RS-485");
373	} else {
374		rs232_property = 0;
375
376		dev_dbg(dev, "port is fixed as RS-485\n");
377	}
378
379	if (!rs232_property) {
380		/*
381		 * Neither the 'transceiver' property nor the PMR indicate
382		 * that this is an RS-232 port, so it must be an RS-485 one.
383		 */
384		ni16550_rs485_setup(&uart->port);
385	}
386
387	ret = serial8250_register_8250_port(uart);
388	if (ret < 0)
389		return ret;
390	data->line = ret;
391
392	platform_set_drvdata(pdev, data);
393	return 0;
394}
395
396static void ni16550_remove(struct platform_device *pdev)
397{
398	struct ni16550_data *data = platform_get_drvdata(pdev);
399
400	serial8250_unregister_port(data->line);
401}
402
403/* NI 16550 RS-485 Interface */
404static const struct ni16550_device_info nic7750 = {
405	.uartclk = 33333333,
406};
407
408/* NI CVS-145x RS-485 Interface */
409static const struct ni16550_device_info nic7772 = {
410	.uartclk = 1843200,
411	.flags = NI_HAS_PMR,
412};
413
414/* NI cRIO-904x RS-485 Interface */
415static const struct ni16550_device_info nic792b = {
416	/* Sets UART clock rate to 22.222 MHz with 1.125 prescale */
417	.uartclk = 22222222,
418	.prescaler = 0x09,
419};
420
421/* NI sbRIO 96x8 RS-232/485 Interfaces */
422static const struct ni16550_device_info nic7a69 = {
423	/* Set UART clock rate to 29.629 MHz with 1.125 prescale */
424	.uartclk = 29629629,
425	.prescaler = 0x09,
426};
427
428static const struct acpi_device_id ni16550_acpi_match[] = {
429	{ "NIC7750",	(kernel_ulong_t)&nic7750 },
430	{ "NIC7772",	(kernel_ulong_t)&nic7772 },
431	{ "NIC792B",	(kernel_ulong_t)&nic792b },
432	{ "NIC7A69",	(kernel_ulong_t)&nic7a69 },
433	{ }
434};
435MODULE_DEVICE_TABLE(acpi, ni16550_acpi_match);
436
437static struct platform_driver ni16550_driver = {
438	.driver = {
439		.name = "ni16550",
440		.acpi_match_table = ni16550_acpi_match,
441	},
442	.probe = ni16550_probe,
443	.remove = ni16550_remove,
444};
445
446module_platform_driver(ni16550_driver);
447
448MODULE_AUTHOR("Emerson Electric Co.");
449MODULE_DESCRIPTION("NI 16550 Driver");
450MODULE_LICENSE("GPL");
~/ Read-only file preview.