This commit is contained in:
Mark Brown
2026-07-31 16:03:30 +01:00
34 changed files with 706 additions and 453 deletions
@@ -9,6 +9,13 @@ title: Maxim MAX310X Advanced Universal Asynchronous Receiver-Transmitter (UART)
maintainers:
- Hugo Villeneuve <hvilleneuve@dimonoff.com>
description:
The MAX310X is a family of SPI/I2C UARTs with one (max3107, max3108),
two (max3109) or four (max14830) channels. Single-channel parts are
described as a serial node with RS-485 properties on the chip node;
multi-channel parts use one "serial@N" child node per channel, each
carrying its own serial/RS-485 properties.
properties:
compatible:
enum:
@@ -49,8 +56,55 @@ required:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
- $ref: /schemas/serial/serial.yaml#
- $ref: /schemas/serial/rs485.yaml#
- if:
properties:
compatible:
contains:
enum:
- maxim,max3107
- maxim,max3108
then:
allOf:
- $ref: /schemas/serial/serial.yaml#
- $ref: /schemas/serial/rs485.yaml#
- if:
properties:
compatible:
contains:
enum:
- maxim,max3109
- maxim,max14830
then:
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^serial@[0-3]$":
type: object
description: A single UART channel of the chip.
allOf:
- $ref: /schemas/serial/serial.yaml#
- $ref: /schemas/serial/rs485.yaml#
properties:
reg:
description: UART channel number on the chip.
maximum: 3
required:
- reg
unevaluatedProperties: false
- if:
properties:
compatible:
contains:
const: maxim,max3109
then:
patternProperties:
"^serial@[23]$": false
unevaluatedProperties: false
@@ -70,5 +124,39 @@ examples:
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
gpio-controller;
#gpio-cells = <2>;
rs485-rts-active-low;
linux,rs485-enabled-at-boot-time;
};
};
- |
#include <dt-bindings/interrupt-controller/irq.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
serial@0 {
compatible = "maxim,max14830";
reg = <0>;
spi-max-frequency = <26000000>;
clocks = <&xtal4m>;
clock-names = "xtal";
interrupt-parent = <&gpio3>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
gpio-controller;
#gpio-cells = <2>;
#address-cells = <1>;
#size-cells = <0>;
serial@0 {
reg = <0>;
rs485-rts-active-low;
linux,rs485-enabled-at-boot-time;
};
serial@2 {
reg = <2>;
rs485-rts-active-low;
};
};
};
@@ -72,6 +72,7 @@ properties:
- rockchip,rk3576-uart
- rockchip,rk3588-uart
- rockchip,rv1103b-uart
- rockchip,rv1106-uart
- rockchip,rv1108-uart
- rockchip,rv1126-uart
- sophgo,sg2044-uart
+7 -7
View File
@@ -443,23 +443,23 @@ static int rs_startup(struct tty_struct *tty, struct serial_state *info)
struct tty_port *port = &info->tport;
unsigned long flags;
int retval=0;
unsigned long page;
void *buffer;
page = get_zeroed_page(GFP_KERNEL);
if (!page)
buffer = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
local_irq_save(flags);
if (tty_port_initialized(port)) {
free_page(page);
kfree(buffer);
goto errout;
}
if (info->xmit.buf)
free_page(page);
kfree(buffer);
else
info->xmit.buf = (unsigned char *) page;
info->xmit.buf = buffer;
#ifdef SERIAL_DEBUG_OPEN
printk("starting up ttys%d ...", info->line);
@@ -537,7 +537,7 @@ static void rs_shutdown(struct tty_struct *tty, struct serial_state *info)
*/
free_irq(IRQ_AMIGA_VERTB, info);
free_page((unsigned long)info->xmit.buf);
kfree(info->xmit.buf);
info->xmit.buf = NULL;
info->IER = 0;
+14 -9
View File
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/serial_core.h>
#include <linux/wordpart.h>
/* Goldfish tty register's offsets */
#define GOLDFISH_TTY_REG_BYTES_READY 0x04
@@ -37,7 +38,6 @@ struct goldfish_tty {
spinlock_t lock;
void __iomem *base;
u32 irq;
int opencount;
struct console console;
u32 version;
struct device *dev;
@@ -49,15 +49,23 @@ static u32 goldfish_tty_line_count = 8;
static u32 goldfish_tty_current_line_count;
static struct goldfish_tty *goldfish_ttys;
static inline void gf_write_addr(unsigned long addr, void __iomem *portl, void __iomem *porth)
{
gf_iowrite32(lower_32_bits(addr), portl);
#ifdef CONFIG_64BIT
gf_iowrite32(upper_32_bits(addr), porth);
#endif
}
static void do_rw_io(struct goldfish_tty *qtty, unsigned long address,
size_t count, bool is_write)
{
unsigned long irq_flags;
void __iomem *base = qtty->base;
spin_lock_irqsave(&qtty->lock, irq_flags);
gf_write_ptr((void *)address, base + GOLDFISH_TTY_REG_DATA_PTR,
base + GOLDFISH_TTY_REG_DATA_PTR_HIGH);
guard(spinlock_irqsave)(&qtty->lock);
gf_write_addr(address, base + GOLDFISH_TTY_REG_DATA_PTR,
base + GOLDFISH_TTY_REG_DATA_PTR_HIGH);
gf_iowrite32(count, base + GOLDFISH_TTY_REG_DATA_LEN);
if (is_write)
@@ -66,8 +74,6 @@ static void do_rw_io(struct goldfish_tty *qtty, unsigned long address,
else
gf_iowrite32(GOLDFISH_TTY_CMD_READ_BUFFER,
base + GOLDFISH_TTY_REG_CMD);
spin_unlock_irqrestore(&qtty->lock, irq_flags);
}
static void goldfish_tty_rw(struct goldfish_tty *qtty, unsigned long addr,
@@ -409,7 +415,7 @@ static void goldfish_tty_remove(struct platform_device *pdev)
{
struct goldfish_tty *qtty = platform_get_drvdata(pdev);
mutex_lock(&goldfish_tty_lock);
guard(mutex)(&goldfish_tty_lock);
unregister_console(&qtty->console);
tty_unregister_device(goldfish_tty_driver, qtty->console.index);
@@ -420,7 +426,6 @@ static void goldfish_tty_remove(struct platform_device *pdev)
goldfish_tty_current_line_count--;
if (goldfish_tty_current_line_count == 0)
goldfish_tty_delete_driver();
mutex_unlock(&goldfish_tty_lock);
}
#ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE
+1 -1
View File
@@ -79,7 +79,7 @@ config HVC_UDBG
config HVC_DCC
bool "ARM JTAG DCC console"
depends on ARM || ARM64
depends on (ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || ARM64
select HVC_DRIVER
select SERIAL_CORE_CONSOLE
help
+2 -2
View File
@@ -651,11 +651,11 @@ static int acpi_serdev_do_lookup(struct acpi_device *adev,
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list,
acpi_serdev_parse_resource, lookup);
acpi_dev_free_resource_list(&resource_list);
if (ret < 0)
return -EINVAL;
acpi_dev_free_resource_list(&resource_list);
return 0;
}
+8
View File
@@ -8,6 +8,7 @@
*/
#include <linux/bits.h>
#include <linux/kconfig.h>
#include <linux/serial_8250.h>
#include <linux/serial_core.h>
#include <linux/dmaengine.h>
@@ -334,6 +335,13 @@ int fintek_8250_probe(struct uart_8250_port *uart);
static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; }
#endif
#if IS_REACHABLE(CONFIG_SERIAL_8250_HUB6)
bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2);
#else
static inline bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
{ return false; }
#endif
#ifdef CONFIG_ARCH_OMAP1
#include <linux/soc/ti/omap1-soc.h>
static inline int is_omap1_8250(struct uart_8250_port *pt)
+18 -1
View File
@@ -23,6 +23,7 @@
* console=uart8250,mmio32,0xff5e0000,115200n8
*/
#include <linux/align.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <linux/console.h>
@@ -177,6 +178,23 @@ OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup);
OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup);
static int __init early_serial8250_xscale_setup(struct earlycon_device *device,
const char *options)
{
/*
* Adjust for BE32 register accesses: drop any hardcoded
* address for the big endian byte target, add it explicitly
* if running on BE32.
*/
device->port.membase = PTR_ALIGN_DOWN(device->port.membase, 4);
if (IS_ENABLED(CONFIG_CPU_ENDIAN_BE32))
device->port.membase += 3;
device->port.regshift = 2;
return early_serial8250_setup(device, options);
}
OF_EARLYCON_DECLARE(uart, "intel,xscale-uart", early_serial8250_xscale_setup);
static int __init early_serial8250_rs2_setup(struct earlycon_device *device,
const char *options)
{
@@ -184,7 +202,6 @@ static int __init early_serial8250_rs2_setup(struct earlycon_device *device,
return early_serial8250_setup(device, options);
}
OF_EARLYCON_DECLARE(uart, "intel,xscale-uart", early_serial8250_rs2_setup);
OF_EARLYCON_DECLARE(uart, "mrvl,mmp-uart", early_serial8250_rs2_setup);
OF_EARLYCON_DECLARE(uart, "mrvl,pxa-uart", early_serial8250_rs2_setup);
+15 -15
View File
@@ -1642,14 +1642,14 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
.exit = pci_xr17v35x_exit,
};
#define CTI_EXAR_DEVICE(devid, bd) { \
PCI_DEVICE_SUB( \
PCI_VENDOR_ID_EXAR, \
PCI_DEVICE_ID_EXAR_##devid, \
PCI_SUBVENDOR_ID_CONNECT_TECH, \
PCI_ANY_ID), 0, 0, \
(kernel_ulong_t)&bd \
}
#define CTI_EXAR_DEVICE(devid, bd) { \
PCI_DEVICE_SUB( \
PCI_VENDOR_ID_EXAR, \
PCI_DEVICE_ID_EXAR_##devid, \
PCI_SUBVENDOR_ID_CONNECT_TECH, \
PCI_ANY_ID), \
.driver_data = (kernel_ulong_t)&bd \
}
#define EXAR_DEVICE(vend, devid, bd) { PCI_DEVICE_DATA(vend, devid, &bd) }
@@ -1658,18 +1658,18 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
PCI_VENDOR_ID_EXAR, \
PCI_DEVICE_ID_EXAR_##devid, \
PCI_SUBVENDOR_ID_IBM, \
PCI_SUBDEVICE_ID_IBM_##sdevid), 0, 0, \
(kernel_ulong_t)&bd \
}
PCI_SUBDEVICE_ID_IBM_##sdevid), \
.driver_data = (kernel_ulong_t)&bd \
}
#define USR_DEVICE(devid, sdevid, bd) { \
PCI_DEVICE_SUB( \
PCI_VENDOR_ID_USR, \
PCI_DEVICE_ID_EXAR_##devid, \
PCI_VENDOR_ID_EXAR, \
PCI_SUBDEVICE_ID_USR_##sdevid), 0, 0, \
(kernel_ulong_t)&bd \
}
PCI_SUBDEVICE_ID_USR_##sdevid), \
.driver_data = (kernel_ulong_t)&bd \
}
static const struct pci_device_id exar_pci_tbl[] = {
EXAR_DEVICE(ACCESSIO, COM_2S, pbn_exar_XR17C15x),
@@ -1726,7 +1726,7 @@ static const struct pci_device_id exar_pci_tbl[] = {
EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4),
EXAR_DEVICE(COMMTECH, 2324PCI335, pbn_fastcom335_4),
EXAR_DEVICE(COMMTECH, 2328PCI335, pbn_fastcom335_8),
{ 0, }
{ }
};
MODULE_DEVICE_TABLE(pci, exar_pci_tbl);
+8
View File
@@ -7,6 +7,8 @@
#include <linux/init.h>
#include <linux/serial_8250.h>
#include "8250.h"
#define HUB6(card, port) \
{ \
.iobase = 0x302, \
@@ -41,6 +43,12 @@ static struct platform_device hub6_device = {
},
};
bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
{
return port1->iobase == port2->iobase && port1->hub6 == port2->hub6;
}
EXPORT_SYMBOL_GPL(hub6_match_port);
static int __init hub6_init(void)
{
return platform_device_register(&hub6_device);
+12
View File
@@ -5,6 +5,7 @@
* Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
*/
#include <linux/align.h>
#include <linux/bits.h>
#include <linux/console.h>
#include <linux/math.h>
@@ -122,6 +123,17 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
if (ret)
goto err_pmruntime;
if (IS_ENABLED(CONFIG_CPU_XSCALE) && type == PORT_XSCALE) {
/*
* Adjust for BE32 register accesses: drop any hardcoded
* address for the big endian byte target, add it explicitly
* if running on BE32.
*/
port->mapbase = PTR_ALIGN_DOWN(port->mapbase, 4);
if (IS_ENABLED(CONFIG_CPU_ENDIAN_BE32))
port->mapbase += 3;
}
/* Get clk rate through clk driver if present */
if (!port->uartclk) {
struct clk *bus_clk;
+1
View File
@@ -284,6 +284,7 @@ static struct platform_driver serial8250_isa_driver = {
.driver = {
.name = "serial8250",
.acpi_match_table = acpi_platform_serial_table,
.probe_type = PROBE_FORCE_SYNCHRONOUS,
},
};
File diff suppressed because it is too large Load Diff
+7 -36
View File
@@ -474,16 +474,10 @@ static void set_io_from_upio(struct uart_port *p)
static void
serial_port_out_sync(struct uart_port *p, int offset, int value)
{
switch (p->iotype) {
case UPIO_MEM:
case UPIO_MEM16:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_AU:
if (uart_iotype_mmio(p->iotype)) {
p->serial_out(p, offset, value);
p->serial_in(p, UART_LCR); /* safe, no side-effects */
break;
default:
} else {
p->serial_out(p, offset, value);
}
}
@@ -2891,13 +2885,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
unsigned int size = serial8250_port_size(up);
struct uart_port *port = &up->port;
switch (port->iotype) {
case UPIO_AU:
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_MEM16:
case UPIO_MEM:
if (uart_iotype_mmio(port->iotype)) {
if (!port->mapbase)
return -EINVAL;
@@ -2911,14 +2899,9 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
return -ENOMEM;
}
}
return 0;
case UPIO_HUB6:
case UPIO_PORT:
} else if (uart_iotype_io(port->iotype)) {
if (!request_region(port->iobase, size, "serial"))
return -EBUSY;
return 0;
case UPIO_UNKNOWN:
break;
}
return 0;
@@ -2929,15 +2912,9 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
unsigned int size = serial8250_port_size(up);
struct uart_port *port = &up->port;
switch (port->iotype) {
case UPIO_AU:
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_MEM16:
case UPIO_MEM:
if (uart_iotype_mmio(port->iotype)) {
if (!port->mapbase)
break;
return;
if (port->flags & UPF_IOREMAP) {
iounmap(port->membase);
@@ -2945,14 +2922,8 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
}
release_mem_region(port->mapbase, size);
break;
case UPIO_HUB6:
case UPIO_PORT:
} else if (uart_iotype_io(port->iotype)) {
release_region(port->iobase, size);
break;
case UPIO_UNKNOWN:
break;
}
}
+19 -21
View File
@@ -19,35 +19,33 @@ static const struct uart_ops *core_port_base_ops;
static int rsa8250_request_resource(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
unsigned long start = UART_RSA_BASE << port->regshift;
unsigned int size = 8 << port->regshift;
unsigned long start;
unsigned int size;
switch (port->iotype) {
case UPIO_HUB6:
case UPIO_PORT:
start += port->iobase;
if (!request_region(start, size, "serial-rsa"))
return -EBUSY;
return 0;
default:
if (!uart_iotype_io(port->iotype))
return -EINVAL;
}
start = UART_RSA_BASE << port->regshift;
start += port->iobase;
size = 8 << port->regshift;
if (!request_region(start, size, "serial-rsa"))
return -EBUSY;
return 0;
}
static void rsa8250_release_resource(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
unsigned long offset = UART_RSA_BASE << port->regshift;
unsigned int size = 8 << port->regshift;
unsigned long offset;
unsigned int size;
switch (port->iotype) {
case UPIO_HUB6:
case UPIO_PORT:
release_region(port->iobase + offset, size);
break;
default:
break;
}
if (!uart_iotype_io(port->iotype))
return;
offset = UART_RSA_BASE << port->regshift;
size = 8 << port->regshift;
release_region(port->iobase + offset, size);
}
static void univ8250_config_port(struct uart_port *port, int flags)
+3 -6
View File
@@ -27,7 +27,6 @@
#include <linux/memblock.h>
#include <linux/dma-mapping.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/gpio/consumer.h>
#include <linux/clk.h>
@@ -1530,16 +1529,14 @@ static int cpm_uart_probe(struct platform_device *ofdev)
/* initialize the device pointer for the port */
pinfo->port.dev = &ofdev->dev;
pinfo->port.irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
if (!pinfo->port.irq)
return -EINVAL;
pinfo->port.irq = platform_get_irq(ofdev, 0);
if (pinfo->port.irq < 0)
return pinfo->port.irq;
ret = cpm_uart_init_port(ofdev->dev.of_node, pinfo);
if (!ret)
return uart_add_one_port(&cpm_reg, &pinfo->port);
irq_dispose_mapping(pinfo->port.irq);
return ret;
}
+5 -12
View File
@@ -75,19 +75,12 @@ static void __init earlycon_print_info(struct earlycon_device *device)
{
struct console *earlycon = device->con;
struct uart_port *port = &device->port;
char ioinfos[64];
if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 ||
port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE)
pr_info("%s%d at MMIO%s %pa (options '%s')\n",
earlycon->name, earlycon->index,
(port->iotype == UPIO_MEM) ? "" :
(port->iotype == UPIO_MEM16) ? "16" :
(port->iotype == UPIO_MEM32) ? "32" : "32be",
&port->mapbase, device->options);
else
pr_info("%s%d at I/O port 0x%lx (options '%s')\n",
earlycon->name, earlycon->index,
port->iobase, device->options);
uart_get_ioinfos(port, ioinfos, sizeof(ioinfos));
pr_info("%s%d%s (options '%s')\n", earlycon->name, earlycon->index,
ioinfos, device->options);
}
static int __init parse_options(struct earlycon_device *device, char *options)
+1 -1
View File
@@ -363,7 +363,7 @@ static int param_set_kgdboc_var(const char *kmessage,
mutex_lock(&config_mutex);
strcpy(config, kmessage);
strscpy(config, kmessage);
/* Chop out \n char as a result of echo */
if (len && config[len - 1] == '\n')
config[len - 1] = '\0';
+10 -2
View File
@@ -608,8 +608,14 @@ static int __init ma35d1serial_console_setup(struct console *co, char *options)
if (!np || !p)
return -ENODEV;
if (of_property_read_u32_array(np, "reg", val32, ARRAY_SIZE(val32)) != 0)
if (of_property_read_u32_array(np, "reg", val32, ARRAY_SIZE(val32)) != 0) {
of_node_put(np);
ma35d1serial_uart_nodes[co->index] = NULL;
return -EINVAL;
}
of_node_put(np);
ma35d1serial_uart_nodes[co->index] = NULL;
p->port.iobase = val32[1];
p->port.membase = ioremap(p->port.iobase, MA35_UART_REG_SIZE);
@@ -648,8 +654,10 @@ static void ma35d1serial_console_init_port(void)
of_node_get(np);
ma35d1serial_uart_nodes[i] = np;
i++;
if (i == MA35_UART_NR)
if (i == MA35_UART_NR) {
of_node_put(np);
break;
}
}
}
}
+1
View File
@@ -724,6 +724,7 @@ static int max3100_probe(struct spi_device *spi)
max3100s[i]->port.ops = &max3100_ops;
max3100s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
max3100s[i]->port.line = i;
max3100s[i]->port.iotype = UPIO_BUS;
max3100s[i]->port.type = PORT_MAX3100;
max3100s[i]->port.dev = &spi->dev;

Some files were not shown because too many files have changed in this diff Show More