mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 11:41:29 -04:00
serial: max310x: honour rs485 properties from per-channel DT subnode
The MAX310x DT binding pulls in /schemas/serial/rs485.yaml via its allOf list, advertising the rs485-* properties defined there - none of which were honoured at runtime, because the driver never called uart_get_rs485_mode(). All channels share the parent SPI/I2C device, so uart_get_rs485_mode() called directly on each port would read the same chip-level fwnode for every call. Walk dev->of_node's children for the "serial@N" subnode with matching reg, and temporarily retarget the parent device's fwnode while uart_get_rs485_mode() runs, so each channel picks up its own subnode's properties. Probe is serialised, so the swap is safe. For single-channel variants (max3107, max3108), fall back to the chip's own fwnode when no subnode is present, so existing DTs that declare rs485 properties at the top level keep working. Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com> Link: https://patch.msgid.link/20260615-b4-max310x-rs485-dt-v3-3-7e79f064bdd7@vaisala.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
f3fd73bf20
commit
bed094602f
@@ -1452,6 +1452,9 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
||||
#endif
|
||||
|
||||
for (i = 0; i < devtype->nr; i++) {
|
||||
struct fwnode_handle *saved_fwnode = dev_fwnode(dev);
|
||||
struct device_node *port_np = NULL;
|
||||
struct device_node *child;
|
||||
unsigned int line;
|
||||
|
||||
line = find_first_zero_bit(max310x_lines, MAX310X_UART_NRMAX);
|
||||
@@ -1461,6 +1464,40 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
||||
}
|
||||
s->p[i].port.line = line;
|
||||
|
||||
/* Locate the matching "serial@i" DT subnode, if any. */
|
||||
for_each_available_child_of_node(dev->of_node, child) {
|
||||
u32 reg;
|
||||
|
||||
if (!of_node_name_eq(child, "serial"))
|
||||
continue;
|
||||
if (of_property_read_u32(child, "reg", ®))
|
||||
continue;
|
||||
if (reg == i) {
|
||||
port_np = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Temporarily retarget dev's fwnode to the per-port subnode
|
||||
* so uart_get_rs485_mode() picks up the per-port properties.
|
||||
* For single-port variants, fall back to the chip's own
|
||||
* fwnode so legacy DTs that declare rs485 properties at the
|
||||
* top level keep working.
|
||||
*/
|
||||
if (port_np) {
|
||||
device_set_node(dev, of_fwnode_handle(port_np));
|
||||
ret = uart_get_rs485_mode(&s->p[i].port);
|
||||
device_set_node(dev, saved_fwnode);
|
||||
of_node_put(port_np);
|
||||
if (ret)
|
||||
goto out_uart;
|
||||
} else if (devtype->nr == 1) {
|
||||
ret = uart_get_rs485_mode(&s->p[i].port);
|
||||
if (ret)
|
||||
goto out_uart;
|
||||
}
|
||||
|
||||
/* Register port */
|
||||
ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
|
||||
if (ret)
|
||||
|
||||
Reference in New Issue
Block a user