Lines Matching +full:uart +full:- +full:16550 +full:- +full:compatible
1 // SPDX-License-Identifier: GPL-2.0+
3 * NI 16550 UART Driver
5 * The National Instruments (NI) 16550 is a UART that is compatible with the
7 * for RS-485 transceiver control. This driver implements support for the
10 * Copyright 2012-2023 National Instruments Corporation
27 /* TFS - TX FIFO Size */
29 /* RFS - RX FIFO Size */
32 /* PMR - Port Mode Register */
34 /* PMR[1:0] - Port Capabilities */
37 #define NI16550_PMR_CAP_RS232 FIELD_PREP(NI16550_PMR_CAP_MASK, 1) /* RS-232 capable */
38 #define NI16550_PMR_CAP_RS485 FIELD_PREP(NI16550_PMR_CAP_MASK, 2) /* RS-485 capable */
39 #define NI16550_PMR_CAP_DUAL FIELD_PREP(NI16550_PMR_CAP_MASK, 3) /* dual-port */
40 /* PMR[4] - Interface Mode */
45 /* PCR - Port Control Register */
48 * ---------------|----------------------|--------------------------
81 pcr = port->serial_in(port, NI16550_PCR_OFFSET); in ni16550_enable_transceivers()
83 dev_dbg(port->dev, "enable transceivers: write pcr: 0x%02x\n", pcr); in ni16550_enable_transceivers()
84 port->serial_out(port, NI16550_PCR_OFFSET, pcr); in ni16550_enable_transceivers()
93 pcr = port->serial_in(port, NI16550_PCR_OFFSET); in ni16550_disable_transceivers()
95 dev_dbg(port->dev, "disable transceivers: write pcr: 0x%02x\n", pcr); in ni16550_disable_transceivers()
96 port->serial_out(port, NI16550_PCR_OFFSET, pcr); in ni16550_disable_transceivers()
111 if ((rs485->flags & SER_RS485_MODE_RS422) || in ni16550_rs485_config()
112 !(rs485->flags & SER_RS485_ENABLED)) { in ni16550_rs485_config()
113 /* RS-422 */ in ni16550_rs485_config()
115 up->acr &= ~NI16550_ACR_AUTO_DTR_EN; in ni16550_rs485_config()
117 /* RS-485 2-wire Auto */ in ni16550_rs485_config()
119 up->acr |= NI16550_ACR_AUTO_DTR_EN; in ni16550_rs485_config()
122 dev_dbg(port->dev, "config rs485: write pcr: 0x%02x, acr: %02x\n", pcr, up->acr); in ni16550_rs485_config()
124 serial_icr_write(up, UART_ACR, up->acr); in ni16550_rs485_config()
137 * connected to RS-485 transceivers in is_pmr_rs232_mode()
144 * If the port is dual-mode capable, then read the mode bit in is_pmr_rs232_mode()
149 * If it is not dual-mode capable, then decide based on the in is_pmr_rs232_mode()
195 port->rs485_config = ni16550_rs485_config; in ni16550_rs485_setup()
196 port->rs485_supported = ni16550_rs485_supported; in ni16550_rs485_setup()
198 * The hardware comes up by default in 2-wire auto mode and we in ni16550_rs485_setup()
201 port->rs485.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND; in ni16550_rs485_setup()
229 port->iotype = UPIO_PORT; in ni16550_get_regs()
230 port->iobase = regs->start; in ni16550_get_regs()
237 port->iotype = UPIO_MEM; in ni16550_get_regs()
238 port->mapbase = regs->start; in ni16550_get_regs()
239 port->mapsize = resource_size(regs); in ni16550_get_regs()
240 port->flags |= UPF_IOREMAP; in ni16550_get_regs()
242 port->membase = devm_ioremap(&pdev->dev, port->mapbase, in ni16550_get_regs()
243 port->mapsize); in ni16550_get_regs()
244 if (!port->membase) in ni16550_get_regs()
245 return -ENOMEM; in ni16550_get_regs()
250 dev_err(&pdev->dev, "no registers defined\n"); in ni16550_get_regs()
251 return -EINVAL; in ni16550_get_regs()
256 * defined, so we may read all-0s or all-1s. For such devices,
259 static u8 ni16550_read_fifo_size(struct uart_8250_port *uart, int reg) in ni16550_read_fifo_size() argument
261 u8 value = serial_in(uart, reg); in ni16550_read_fifo_size()
273 up->mcr |= UART_MCR_CLKSEL; in ni16550_set_mctrl()
280 struct device *dev = &pdev->dev; in ni16550_probe()
281 struct uart_8250_port uart = {}; in ni16550_probe() local
292 return -ENOMEM; in ni16550_probe()
294 spin_lock_init(&uart.port.lock); in ni16550_probe()
300 ret = ni16550_get_regs(pdev, &uart.port); in ni16550_probe()
305 serial8250_set_defaults(&uart); in ni16550_probe()
309 uart.port.dev = dev; in ni16550_probe()
310 uart.port.irq = irq; in ni16550_probe()
311 uart.port.irqflags = IRQF_SHARED; in ni16550_probe()
312 uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF in ni16550_probe()
314 uart.port.startup = ni16550_port_startup; in ni16550_probe()
315 uart.port.shutdown = ni16550_port_shutdown; in ni16550_probe()
320 txfifosz = ni16550_read_fifo_size(&uart, NI16550_TFS_OFFSET); in ni16550_probe()
321 rxfifosz = ni16550_read_fifo_size(&uart, NI16550_RFS_OFFSET); in ni16550_probe()
323 dev_dbg(dev, "NI 16550 has TX FIFO size %u, RX FIFO size %u\n", in ni16550_probe()
326 uart.port.type = PORT_16550A; in ni16550_probe()
327 uart.port.fifosize = txfifosz; in ni16550_probe()
328 uart.tx_loadsz = txfifosz; in ni16550_probe()
329 uart.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10; in ni16550_probe()
330 uart.capabilities = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR; in ni16550_probe()
334 * - static declaration in this driver (for older ACPI IDs) in ni16550_probe()
335 * - a "clock-frquency" ACPI in ni16550_probe()
337 if (info->uartclk) in ni16550_probe()
338 uart.port.uartclk = info->uartclk; in ni16550_probe()
339 if (device_property_read_u32(dev, "clock-frequency", in ni16550_probe()
340 &uart.port.uartclk)) { in ni16550_probe()
341 data->clk = devm_clk_get_enabled(dev, NULL); in ni16550_probe()
342 if (!IS_ERR(data->clk)) in ni16550_probe()
343 uart.port.uartclk = clk_get_rate(data->clk); in ni16550_probe()
346 if (!uart.port.uartclk) { in ni16550_probe()
348 ret = -ENODEV; in ni16550_probe()
352 if (info->prescaler) in ni16550_probe()
353 prescaler = info->prescaler; in ni16550_probe()
354 device_property_read_u32(dev, "clock-prescaler", &prescaler); in ni16550_probe()
357 uart.port.set_mctrl = ni16550_set_mctrl; in ni16550_probe()
358 ni16550_config_prescaler(&uart, (u8)prescaler); in ni16550_probe()
362 * The determination of whether or not this is an RS-485 or RS-232 port in ni16550_probe()
363 * can come from the PMR (if present), otherwise we're solely an RS-485 in ni16550_probe()
366 * This is a device-specific property, and there are old devices in the in ni16550_probe()
371 rs232_property = strncmp(portmode, "RS-232", 6) == 0; in ni16550_probe()
374 rs232_property ? "RS-232" : "RS-485"); in ni16550_probe()
375 } else if (info->flags & NI_HAS_PMR) { in ni16550_probe()
376 rs232_property = is_pmr_rs232_mode(&uart); in ni16550_probe()
379 rs232_property ? "RS-232" : "RS-485"); in ni16550_probe()
383 dev_dbg(dev, "port is fixed as RS-485\n"); in ni16550_probe()
389 * that this is an RS-232 port, so it must be an RS-485 one. in ni16550_probe()
391 ni16550_rs485_setup(&uart.port); in ni16550_probe()
394 ret = serial8250_register_8250_port(&uart); in ni16550_probe()
397 data->line = ret; in ni16550_probe()
410 serial8250_unregister_port(data->line); in ni16550_remove()
414 /* NI 16550 RS-485 Interface */
419 /* NI CVS-145x RS-485 Interface */
425 /* NI cRIO-904x RS-485 Interface */
427 /* Sets UART clock rate to 22.222 MHz with 1.125 prescale */
432 /* NI sbRIO 96x8 RS-232/485 Interfaces */
434 /* Set UART clock rate to 29.629 MHz with 1.125 prescale */
460 MODULE_DESCRIPTION("NI 16550 Driver");